github.com/igggame/nebulas-go@v2.1.0+incompatible/nebtestkit/cases/contract/contract.bankvault.test.js (about)

     1  'use strict';
     2  
     3  var HttpRequest = require("../../node-request");
     4  
     5  var Wallet = require("nebulas");
     6  var Account = Wallet.Account;
     7  var Transaction = Wallet.Transaction;
     8  var Utils = Wallet.Utils;
     9  var Unit = Wallet.Unit;
    10  
    11  var expect = require('chai').expect;
    12  var BigNumber = require('bignumber.js');
    13  var FS = require("fs");
    14  
    15  var neb = new Wallet.Neb();
    16  neb.setRequest(new HttpRequest("http://localhost:8685"));
    17  var ChainID = 100;
    18  var sourceAccount = new Account("a6e5eb290e1438fce79f5cb8774a72621637c2c9654c8b2525ed1d7e4e73653f");
    19  
    20  var coinbase = "eb31ad2d8a89a0ca6935c308d5425730430bc2d63f2573b8";
    21  var coinState;
    22  
    23  // deploy a new contract each run 
    24  var redeploy = process.env.REDEPLOY || true;
    25  var scriptType = process.env.script || 'js';
    26  var env = process.env.NET || 'local';
    27  var blockInterval = 15;
    28  
    29  // mocha cases/contract/xxx testneb1 -t 200000
    30  var args = process.argv.splice(2);
    31  env = args[1];
    32  if (env !== "local" && env !== "testneb1" && env !== "testneb2" && env !== "testneb3") {
    33      env = "local";
    34  }
    35  console.log("env:", env);
    36  
    37  if (env === 'local') {
    38      neb.setRequest(new HttpRequest("http://127.0.0.1:8685"));//https://testnet.nebulas.io
    39  	ChainID = 100;
    40      sourceAccount = new Wallet.Account("1d3fe06a53919e728315e2ccca41d4aa5b190845a79007797517e62dbc0df454");
    41      coinbase = "n1QZMXSZtW7BUerroSms4axNfyBGyFGkrh5";
    42      if (!redeploy) {
    43          contractAddr = "e5a02995444628cf7935e3ef8b613299a2d97e6d188ce808";  //js
    44          // contractAddr = "557fccaf2f05d4b46156e9b98ca9726f1c9e91d95d3830a7";  //ts
    45      }
    46  
    47  } else if (env === 'testneb1') {
    48      neb.setRequest(new HttpRequest("http://35.182.48.19:8685"));
    49      ChainID = 1001;
    50      sourceAccount = new Wallet.Account("43181d58178263837a9a6b08f06379a348a5b362bfab3631ac78d2ac771c5df3");
    51      coinbase = "0b9cd051a6d7129ab44b17833c63fe4abead40c3714cde6d";
    52      if (!redeploy) {
    53          contractAddr = "a506c769c3e8832f9bfaea99ba667d0ebb44a79136696045";
    54      }
    55  
    56  } else if (env === "testneb2") {
    57      neb.setRequest(new HttpRequest("http://34.205.26.12:8685"));
    58      ChainID = 1002;
    59      sourceAccount = new Wallet.Account("25a3a441a34658e7a595a0eda222fa43ac51bd223017d17b420674fb6d0a4d52");
    60      coinbase = "n1SAeQRVn33bamxN4ehWUT7JGdxipwn8b17";
    61      if (!redeploy) {
    62          contractAddr = "";
    63      }
    64  }else if (env === "testneb3") {
    65      neb.setRequest(new HttpRequest("http://35.177.214.138:8685"));
    66      ChainID = 1003;
    67      sourceAccount = new Wallet.Account("43181d58178263837a9a6b08f06379a348a5b362bfab3631ac78d2ac771c5df3");
    68      coinbase = "0b9cd051a6d7129ab44b17833c63fe4abead40c3714cde6d";
    69      if (!redeploy) {
    70          contractAddr = "";
    71      }
    72  }
    73  
    74  
    75  
    76  var from;
    77  var fromState;
    78  var contractAddr;
    79  var initFromBalance = 10;
    80  
    81  
    82  
    83  /*
    84   * set this value according to the status of your testnet.
    85   * the smaller the value, the faster the test, with the risk of causing error
    86   */
    87  var maxCheckTime = 15;
    88  var checkTimes = 0;
    89  var beginCheckTime;
    90  
    91  function checkTransaction(hash, callback) {
    92      console.log("==>checkTransaction");
    93      if (checkTimes === 0) {
    94          beginCheckTime = new Date().getTime();
    95      }
    96      checkTimes += 1;
    97      if (checkTimes > maxCheckTime) {
    98          console.log("check tx receipt timeout: " + hash);
    99          checkTimes = 0;
   100          callback();
   101          return
   102      }
   103  
   104      neb.api.getTransactionReceipt(hash).then(function(resp) {
   105          console.log("tx receipt: " + JSON.stringify(resp))
   106          if (resp.status === 2) {
   107              setTimeout(function(){
   108                  checkTransaction(hash, callback)
   109              }, 5000)
   110          } else {
   111              checkTimes = 0;
   112              var endCheckTime = new Date().getTime();
   113              console.log("check tx time: : " + (endCheckTime - beginCheckTime) / 1000);
   114              callback(resp);
   115              return
   116          }
   117  
   118      }).catch(function (err) {
   119          console.log("fail to get tx receipt hash: '" + hash + "' probably being packing, continue checking...")
   120          console.log(err);
   121          console.log(err.error);
   122          setTimeout(function(){
   123              checkTransaction(hash, callback)
   124          }, 5000)
   125      });
   126  }
   127  
   128  function deployContract(testInput, done) {
   129      console.log("==> deployContract");
   130      neb.api.getAccountState(from.getAddressString()).then(function(state){
   131          fromState = state;
   132          console.log("from state: " + JSON.stringify(fromState));
   133      }).then(function(){
   134          var filepath = "../nf/nvm/test/bank_vault_contract." + testInput.contractType;
   135          console.log("deploying contract: " + filepath);
   136          var bankvault = FS.readFileSync(filepath, "utf-8");
   137          var contract = {
   138              "source": bankvault,
   139              "sourceType": testInput.contractType,
   140              "args": ""
   141          }
   142  
   143          var tx = new Transaction(ChainID, from, from, 0, parseInt(fromState.nonce) + 1, 1000000, testInput.gasLimit, contract);
   144          tx.signTransaction();
   145          return neb.api.sendRawTransaction(tx.toProtoString());
   146      }).catch (function(err){
   147          console.log(err.error);
   148          done(err);
   149      }).then(function(resp){
   150          console.log("111: result", resp);
   151          expect(resp).to.be.have.property('txhash');
   152          expect(resp).to.be.have.property('contract_address');
   153          contractAddr = resp.contract_address;
   154          console.log("deploy contract return: " + JSON.stringify(resp));
   155  
   156          checkTransaction(resp.txhash, function(resp){
   157              expect(resp).to.not.be.a('undefined');
   158              expect(resp).to.be.have.property('status').equal(1);
   159  
   160              neb.api.getAccountState(contractAddr).then(function(state){
   161                  console.log("contract: " + contractAddr + ", state: " + JSON.stringify(state));
   162                  done();
   163              });
   164          });
   165      });
   166  }
   167  var fromBalanceBefore,
   168      contractBalanceBefore,
   169      fromBalanceChange,
   170      contractBalanceChange,
   171      coinBalanceBefore,
   172      gasUsed,
   173      gasPrice,
   174      txInfo = {};
   175  
   176  function testSave(testInput, testExpect, done) {
   177      console.log("==> testSave");
   178  
   179      var call = {
   180          "function": testInput.func,
   181          "args": testInput.args
   182      }
   183  
   184      neb.api.getAccountState(contractAddr).then(function(state){
   185          console.log("[before save] contract state: " + JSON.stringify(state));
   186          contractBalanceBefore = new BigNumber(state.balance);
   187  
   188          return neb.api.getAccountState(from.getAddressString());
   189      }).then(function(state){
   190          console.log("[before save] from state: " + JSON.stringify(state));
   191          fromBalanceBefore = state.balance;
   192          txInfo.call = call;
   193          txInfo.nonce = parseInt(state.nonce) + 1;
   194  
   195          neb.api.getAccountState(coinbase).then(function(state){
   196              console.log("[before save] coinbase state:" + JSON.stringify(state));
   197              coinBalanceBefore = state.balance;
   198          });
   199         
   200          return neb.api.estimateGas(from.getAddressString(), contractAddr,
   201                  testInput.value, txInfo.nonce, testInput.gasPrice, testInput.gasLimit, txInfo.call);
   202  
   203      }).then(function(resp){
   204          expect(resp).to.have.property('gas');
   205          gasUsed = resp.gas;
   206  
   207          var tx = new Transaction(ChainID, from, contractAddr, 
   208              testInput.value, txInfo.nonce, 0, testInput.gasLimit, call);
   209          tx.signTransaction();
   210          return neb.api.sendRawTransaction(tx.toProtoString());
   211      }).then(function(resp){
   212          expect(resp).to.have.property('txhash');
   213          checkTransaction(resp.txhash, function(receipt){
   214  
   215              if (testExpect.canExecuteTx) {
   216                  expect(receipt).to.have.property('status').equal(1);
   217              } else {
   218                  expect(receipt).to.not.have.property('status');
   219              }
   220  
   221              neb.api.getAccountState(receipt.from).then(function(state){
   222  
   223                  // from balance change
   224                  fromBalanceChange = new BigNumber(fromBalanceBefore).sub(new BigNumber(state.balance));
   225                  console.log("[after save] from state: " + JSON.stringify(state) + ", balance change: " + fromBalanceChange);
   226  
   227                  return neb.api.getAccountState(receipt.to);
   228              }).then(function(cstate){
   229                  contractBalanceChange = new BigNumber(cstate.balance).sub(contractBalanceBefore);
   230                  console.log("[after save] contract state: " + JSON.stringify(cstate));
   231  
   232                  return neb.api.getAccountState(coinbase);
   233              }).then(function(state){
   234                  var coinbalancechange = new BigNumber(state.balance).sub(new BigNumber(coinBalanceBefore))
   235                      .mod(new BigNumber(1.4269).mul(new BigNumber(10).pow(new BigNumber(18))));
   236                  console.log("[after save] coinbase state:" + JSON.stringify(state) + ", balance change: " + coinbalancechange);
   237                  return neb.api.gasPrice();
   238              }).then(function(resp){
   239                  expect(resp).to.have.property('gas_price');
   240                  console.log("[after save] gas price:" + resp['gas_price'] + ", gas used: " + gasUsed);
   241                  gasPrice = resp['gas_price'];
   242                  var isEqual = fromBalanceChange.equals(new BigNumber(gasUsed)
   243                                                  .mul(new BigNumber(gasPrice))
   244                                                  .add(new BigNumber(testInput.value)));     
   245                  expect(isEqual).to.be.true;
   246  
   247                  isEqual = contractBalanceChange.equals(new BigNumber(testInput.value));
   248                  expect(isEqual).to.be.true; 
   249                  done();
   250              }).catch(function(err){
   251                  done(err);
   252              });
   253          });
   254      }).catch(function(err){
   255          if (testExpect.hasError) {
   256              try {
   257                  expect(err.error).to.have.property('error').equal(testExpect.errorMsg);
   258                  done();
   259              } catch (e) {
   260                  done(err)
   261              }
   262          } else {
   263              console.log(err.error);
   264              done(err)
   265          }
   266      });
   267  }
   268  
   269  function testTakeout(testInput, testExpect, done) {
   270      console.log("==>testTakeout");
   271      neb.api.getAccountState(contractAddr).then(function(state){
   272          console.log("[before take] contract state: " + JSON.stringify(state));
   273          contractBalanceBefore = new BigNumber(state.balance);
   274  
   275          return neb.api.getAccountState(from.getAddressString());
   276      }).then(function(state){
   277          console.log("[before take] from state: " + JSON.stringify(state));
   278          fromBalanceBefore = state.balance;
   279  
   280          neb.api.getAccountState(coinbase).then(function(state){
   281              console.log("[before take] coinbase state:" + JSON.stringify(state));
   282              coinBalanceBefore = state.balance;
   283          });
   284  
   285          var call = {
   286              "function": testInput.func,
   287              "args": testInput.args
   288          }
   289          var tx = new Transaction(ChainID, from, contractAddr, 
   290              testInput.value, parseInt(state.nonce) + 1, 0, testInput.gasLimit, call);
   291          tx.signTransaction();
   292  
   293          neb.api.estimateGas(from.getAddressString(), contractAddr,
   294              testInput.value, parseInt(state.nonce) + 1, testInput.gasPrice, testInput.gasLimit, call).then(function(resp){
   295                          expect(resp).to.have.property('gas');
   296                          gasUsed = resp.gas;
   297          }).catch(function(err) {
   298              // do nothing
   299          });
   300  
   301          return neb.api.sendRawTransaction(tx.toProtoString());
   302      }).then(function(resp){
   303          expect(resp).to.have.property('txhash');
   304          checkTransaction(resp.txhash, function(receipt){
   305              try {
   306                  console.log("22: receipt", receipt);
   307                  if (testExpect.canExecuteTx) {
   308                      expect(receipt).to.have.property('status').equal(1);
   309                  } else {
   310                      expect(receipt).to.have.property('status').equal(0);
   311                  }
   312  
   313                  console.log("333");
   314                  neb.api.getAccountState(receipt.from).then(function (state) {
   315  
   316                      // from balance change
   317                      fromBalanceChange = new BigNumber(state.balance).sub(new BigNumber(fromBalanceBefore));
   318                      console.log("[after take] from state: " + JSON.stringify(state) + ", balance change: " + fromBalanceChange);
   319  
   320                      return neb.api.getAccountState(receipt.to);
   321                  }).then(function (cstate) {
   322  
   323                      return neb.api.getAccountState(coinbase).then(function (state) {
   324  
   325                          var coinbalancechange = new BigNumber(state.balance).sub(new BigNumber(coinBalanceBefore))
   326                              .mod(new BigNumber(1.4269).mul(new BigNumber(10).pow(new BigNumber(18))));
   327                          console.log("[after take] coinbase state:" + JSON.stringify(state) + ", balance change: " + coinbalancechange);
   328  
   329                          var chg = contractBalanceBefore.sub(new BigNumber(cstate.balance));
   330                          console.log("[after take] contract state: " + JSON.stringify(cstate) + ", balance change: " + chg);
   331  
   332                          if (testExpect.canExecuteTx) {
   333                              var isEqual = chg.equals(new BigNumber(testExpect.takeBalance));
   334                              expect(isEqual).to.be.true;
   335                          }
   336  
   337                          return neb.api.getEventsByHash(receipt.hash);
   338                      });
   339  
   340                  }).then(function (evtResp) {
   341  
   342                      if (!testExpect.canExecuteTx) {
   343  
   344                          expect(evtResp.events[0].topic).to.equal(testExpect.eventTopic);
   345                          done();
   346  
   347                      } else {
   348                          neb.api.gasPrice().then(function (resp) {
   349                              expect(resp).to.have.property('gas_price');
   350                              console.log("[after take] gas price:" + resp['gas_price'] + ", gas used: " + gasUsed);
   351                              gasPrice = resp['gas_price'];
   352  
   353                              var t = new BigNumber(testExpect.takeBalance).sub(new BigNumber(gasUsed)
   354                                  .mul(new BigNumber(gasPrice)));
   355                              var isEqual = fromBalanceChange.equals(t);
   356  
   357                              expect(isEqual).to.be.true;
   358                              done();
   359                          }).catch(function (err) {
   360                              done(err);
   361                          });
   362                      }
   363                  }).catch(function (err) {
   364                      console.log(err.error);
   365                      done(err)
   366                  });
   367              } catch (err) {
   368                  console.log(JSON.stringify(err));
   369                  done(err)
   370              }
   371          })
   372      }).catch(function(err){
   373          console.log(err.error);
   374          if (testExpect.hasError) {
   375              try {
   376                  expect(err.error).to.have.property('error').equal(testExpect.errorMsg)
   377                  done();
   378              } catch (e) {
   379                  done(err)
   380              }
   381          } else {
   382              done(err)
   383          }
   384      });
   385  }
   386  
   387  function testVerifyAddress(testInput, testExpect, done) {
   388      console.log("==> testVerifyAddress");
   389      neb.api.getAccountState(contractAddr).then(function(state){
   390          console.log("[before verify] contract state: " + JSON.stringify(state));
   391          contractBalanceBefore = new BigNumber(state.balance);
   392  
   393          return neb.api.getAccountState(from.getAddressString());
   394      }).then(function(state){
   395          console.log("[before verify] from state: " + JSON.stringify(state));
   396          fromBalanceBefore = state.balance;
   397  
   398          neb.api.getAccountState(coinbase).then(function(state){
   399              console.log("[before verify] coinbase state:" + JSON.stringify(state));
   400              coinBalanceBefore = state.balance;
   401          });
   402  
   403          var call = {
   404              "function": testInput.func,
   405              "args": testInput.args
   406          }
   407          return neb.api.call(from.getAddressString(), contractAddr, testInput.value, parseInt(state.nonce) + 1, testInput.gasPrice, testInput.gasLimit, call);
   408      }).then(resp => {
   409          console.log("response: " + JSON.stringify(resp));
   410          expect(resp).to.have.property('result')
   411          expect(JSON.parse(resp.result)).to.have.property('valid').equal(testExpect.valid);
   412          done();
   413      }).catch(err => done(err));
   414  }
   415  
   416  function claimNas(contractType, done) {
   417      console.log("==> claimNas");
   418      from = Account.NewAccount();
   419  
   420      console.log("from addr:" + from.getAddressString());
   421      console.log("source addr:" + sourceAccount.getAddressString());
   422  
   423      neb.api.getAccountState(sourceAccount.getAddressString()).then(function(resp){
   424  
   425          console.log("source state:" + JSON.stringify(resp));
   426          var tx = new Transaction(ChainID, sourceAccount, from, Unit.nasToBasic(initFromBalance), parseInt(resp.nonce) + 1, 0, 2000000);
   427          tx.signTransaction();
   428          return neb.api.sendRawTransaction(tx.toProtoString());
   429      }).then(function(resp){
   430          console.log("send claim tx result:" + JSON.stringify(resp));
   431          checkTransaction(resp.txhash, function(resp){
   432              expect(resp).to.not.be.a('undefined');
   433              expect(resp).to.be.have.property('status').equal(1);
   434              console.log("complete from address claim.")
   435  
   436              if (redeploy) {
   437                  var testInput = {
   438                      contractType: contractType,
   439                      gasLimit: 2000000,
   440                      gasPrice: 1000000,
   441                  };
   442                  redeploy = false;
   443                  deployContract(testInput, done);
   444              } else {
   445                  done();
   446              }
   447          });
   448      }).catch(function(err){
   449          console.log("claim token failed: " + JSON.stringify(err))
   450          done(err)
   451      });
   452  }
   453  
   454  describe('bankvault.' + scriptType, function() {
   455      
   456  
   457      describe('1. take: normal', function() {
   458          before(function(done){
   459              claimNas(scriptType, done);
   460          });
   461  
   462          it('save before take', function(done){
   463              var testInput = {
   464                  gasLimit: 2000000,
   465                  gasPrice: 1000000,
   466  
   467                  func: "save",
   468                  args: "[0]",
   469                  value: 20000000000,
   470              };
   471  
   472              var testExpect = {
   473                  canExecuteTx: true
   474              };
   475  
   476              testSave(testInput, testExpect, done);
   477          });
   478  
   479          it('call takeout()', function(done){
   480  
   481              // take
   482              var testInput = {
   483                  gasLimit: 2000000,
   484                  gasPrice: 1000000,
   485  
   486                  func: "takeout",
   487                  args: "[10000000000]",
   488                  value: "0"  //no use
   489              }
   490  
   491              var testExpect = {
   492                  canExecuteTx: true,
   493                  takeBalance: "10000000000"
   494              }
   495  
   496              testTakeout(testInput, testExpect, done);
   497          });
   498      });
   499  
   500      describe("2. take: insufficient balance", function(){
   501          before(function(done){
   502              claimNas(scriptType, done);
   503          });
   504  
   505          it('save before take', function(done){
   506              var testInput = {
   507                  gasLimit: 2000000,
   508                  gasPrice: 1000000,
   509  
   510                  func: "save",
   511                  args: "[0]",
   512                  value: 20000000000,
   513              }
   514      
   515              var testExpect = {
   516                  canExecuteTx: true
   517              }
   518      
   519              testSave(testInput, testExpect, done);
   520          });
   521      
   522          it('2-1. transfer > balance', function(done){
   523              // take
   524              var testInput = {
   525                  gasLimit: 2000000,
   526                  gasPrice: 1000000,
   527                  func: "takeout",
   528                  args: "[40000000000]",
   529                  value: "0"  //no use
   530              }
   531      
   532              var testExpect = {
   533                  canExecuteTx: false,  // actually, should be `false`
   534                  takeBalance: '40000000000',  // same with testInput.args[0]
   535                  // eventTopic: 'chain.executeTxFailed',
   536                  eventTopic: 'chain.transactionResult',
   537                  hasError: true,
   538                  errorMsg: 'execution failed'
   539              }
   540      
   541              testTakeout(testInput, testExpect, done);
   542          });
   543  
   544          it('2-2. transfer = 0', function(done){
   545              // take
   546              var testInput = {
   547                  gasLimit: 2000000,
   548                  gasPrice: 1000000,
   549  
   550                  func: "takeout",
   551                  args: "[0]",
   552                  value: "0"  //no use
   553              }
   554      
   555              var testExpect = {
   556                  canExecuteTx: true,  // actually, should be `false`
   557                  takeBalance: '0',  // same with testInput.args[0]
   558              }
   559      
   560              testTakeout(testInput, testExpect, done);
   561          });
   562  
   563          it('2-3. transfer < 0', function(done){
   564              // take
   565              var testInput = {
   566                  gasLimit: 2000000,
   567                  gasPrice: 1000000,
   568  
   569                  func: "takeout",
   570                  args: "[-40000000000]",
   571                  value: "0"  //no use
   572              }
   573      
   574              var testExpect = {
   575                  canExecuteTx: false,  // actually, should be `false`
   576                  takeBalance: '-40000000000',  // same with testInput.args[0]
   577                  // eventTopic: 'chain.executeTxFailed',
   578                  eventTopic: 'chain.transactionResult',
   579                  hasError: true,
   580                  errorMsg: 'execution failed'
   581              }
   582      
   583              testTakeout(testInput, testExpect, done);
   584          });
   585      });
   586  
   587      describe("3. take: lt-height", () => {
   588          before(done => {
   589              claimNas(scriptType, done);
   590          });
   591  
   592          it('save(40) before take', done => {
   593              var testInput = {
   594                  gasLimit: 2000000,
   595                  gasPrice: 1000000,
   596  
   597                  func: "save",
   598                  args: "[15]",
   599                  value: 20000000000,
   600              }
   601      
   602              var testExpect = {
   603                  canExecuteTx: true
   604              }
   605      
   606              testSave(testInput, testExpect, done);
   607          });
   608      
   609          it('call takeout()', done => {
   610              // take
   611              var testInput = {
   612                  gasLimit: 2000000,
   613                  gasPrice: 1000000,
   614  
   615                  func: "takeout",
   616                  args: "[10000000000]",
   617                  value: "0"  //no use
   618              }
   619      
   620              var testExpect = {
   621                  canExecuteTx: false,
   622                  takeBalance: '10000000000',  // same with testInput.args[0]
   623                  // eventTopic: 'chain.executeTxFailed'
   624                  eventTopic: 'chain.transactionResult'
   625              }
   626      
   627              testTakeout(testInput, testExpect, done);
   628          });
   629  
   630          it('call takeout() after 25 blocks', done => {
   631              // take
   632              var testInput = {
   633                  gasLimit: 2000000,
   634                  gasPrice: 1000000,
   635  
   636                  func: "takeout",
   637                  args: "[10000000000]",
   638                  value: "0"  //no use
   639              }
   640      
   641              var testExpect = {
   642                  canExecuteTx: true,
   643                  takeBalance: '10000000000'  // same with testInput.args[0]
   644              }
   645              
   646              setTimeout(() => {
   647                  testTakeout(testInput, testExpect, done);
   648              }, 25 * blockInterval * 1000);
   649              
   650          });
   651      });
   652      
   653      describe("4. take: no deposit", function(){
   654          before(function(done){
   655              claimNas(scriptType, done);
   656          });
   657  
   658          it('call takeout()', function(done){
   659      
   660              // take
   661              var testInput = {
   662                  gasLimit: 2000000,
   663                  gasPrice: 1000000,
   664  
   665                  func: "takeout",
   666                  args: "[10000000000]",
   667                  value: "0"  //no use
   668              }
   669      
   670              var testExpect = {
   671                  canExecuteTx: false , 
   672                  takeBalance: '0',
   673                  // eventTopic: 'chain.executeTxFailed'
   674                  eventTopic: 'chain.transactionResult'
   675              }
   676      
   677              testTakeout(testInput, testExpect, done);
   678          });
   679      });
   680  
   681      describe("5. save", function(){
   682          before(function(done){
   683              claimNas(scriptType, done);
   684          });
   685  
   686          it('5-1. save non-negative value', function(done){
   687              var testInput = {
   688                  gasLimit: 2000000,
   689                  gasPrice: 1000000,
   690  
   691                  func: "save",
   692                  args: "[0]",
   693                  value: 10000000000,
   694              }
   695      
   696              var testExpect = {
   697                  canExecuteTx: true
   698              }
   699      
   700              testSave(testInput, testExpect, done);
   701          });
   702  
   703          it('5-2. save negative value', function(done){
   704              var testInput = {
   705                  gasLimit: 2000000,
   706                  gasPrice: 1000000,
   707  
   708                  func: "save",
   709                  args: "[0]",
   710                  value: -20000000000,
   711              }
   712      
   713              var testExpect = {
   714                  hasError: true,
   715                  errorMsg: "invalid value"
   716              }
   717      
   718              testSave(testInput, testExpect, done);
   719          });
   720  
   721          it('5-3. save negative height', done => {
   722              var testInput = {
   723                  gasLimit: 2000000,
   724                  gasPrice: 1000000,
   725                  func: "save",
   726                  args: "[-500]",
   727                  value: 20000000000,
   728              }
   729      
   730              var testExpect = {
   731                  canExecuteTx: true
   732              }
   733      
   734              testSave(testInput, testExpect, done);
   735          });
   736      });
   737  
   738      describe('6. verifyAddress', () => {
   739  
   740          before(function(done){
   741              claimNas(scriptType, done);
   742          });
   743  
   744          it('6-1. legal address', done => {
   745              var testInput = {
   746                  value: "0",
   747                  gasLimit: 2000000,
   748                  gasPrice: 1000000,
   749                  func: "verifyAddress",
   750                  args: "[\"n1QZMXSZtW7BUerroSms4axNfyBGyFGkrh5\"]"
   751              }
   752      
   753              var testExpect = {
   754                  valid: true
   755              }
   756  
   757              testVerifyAddress(testInput, testExpect, done);
   758          });
   759  
   760          it('6-3. illegal address', done => {
   761              var testInput = {
   762                  value: "0",
   763                  gasLimit: 2000000,
   764                  gasPrice: 1000000,
   765                  func: "verifyAddress",
   766                  args: "[\"slfjlsalfksdflsfjks\"]"
   767              }
   768      
   769              var testExpect = {
   770                  valid: false
   771              }
   772  
   773              testVerifyAddress(testInput, testExpect, done);
   774          });
   775      });
   776  });
   777