智能合约出现了问题:无法读取未定义的属性 ‘prefix’。

huangapple go评论58阅读模式
英文:

Smart contract panicked: cannot read property 'prefix' of undefined\n

问题

我正在尝试与智能合约方法交互,但出现以下错误 -

  ExecutionError: "Smart contract panicked: cannot read property 'prefix' of undefined" +
      '    at reconstruct (build/microsoft.js:994)\n' +
      '    at _reconstruct (build/microsoft.js:1102)\n' +
      '    at buy (build/microsoft.js:1137)\n'

以下是我的智能合约:

import { NearBindgen, call, view, UnorderedMap, initialize } from 'near-sdk-js';

@NearBindgen({})
export class ExchangeContractMicrosoft {
  private stocks: UnorderedMap<number> = new UnorderedMap<number>(
    'unique-id-map1',
  );

  constructor() {
    this.stocks.set('msft', 10000000);
  }

  @call({})
  buy(): void {
    const stock: string = 'msft';
    this.checkStock(stock, 1);
    this.stocks.set('msft', this.stocks.get(stock) - 1);
  }

  private checkStock(stock: string, value: number): void {
    if (this.stocks.get(stock) < value) {
      throw 'Not enough stocks';
    }
  }
}

我尝试使用以下方式进行交互:

near call sipars.testnet buy '{}' --accountId sipars.testnet --gas=300000000000000

是否有人能帮忙找出我做错了什么?

英文:

I am trying to interact with a smart contract method and getting the error -

  ExecutionError: &quot;Smart contract panicked: cannot read property &#39;prefix&#39; of undefined\n&quot; +
      &#39;    at reconstruct (build/microsoft.js:994)\n&#39; +
      &#39;    at _reconstruct (build/microsoft.js:1102)\n&#39; +
      &#39;    at buy (build/microsoft.js:1137)\n&#39;

Below is my smart contract :

import { NearBindgen, call, view, UnorderedMap, initialize } from &#39;near-sdk-js&#39;;

@NearBindgen({})
export class ExchangeContractMicrosoft {
  private stocks: UnorderedMap&lt;number&gt; = new UnorderedMap&lt;number&gt;(
    &#39;unique-id-map1&#39;,
  );

  constructor() {
    this.stocks.set(&#39;msft&#39;, 10000000);
  }

  @call({})
  buy(): void {
    const stock: string = &#39;msft&#39;;
    this.checkStock(stock, 1);
    this.stocks.set(&#39;msft&#39;, this.stocks.get(stock) - 1);
  }

  private checkStock(stock: string, value: number): void {
    if (this.stocks.get(stock) &lt; value) {
      throw &#39;Not enough stocks&#39;;
    }
  }
}

I am trying to interact using :

near call sipars.testnet buy &#39;{}&#39; --accountId sipars.testnet --gas=300000000000000

Could someone help figure out what I am doing wrong ?

答案1

得分: 1

这很可能是因为您在首次部署智能合约后对其进行了更改所导致的。这样,您可能会访问尚未定义的对象。如果您在已经部署合同后尝试初始化其他对象,这种情况可能会发生。

例如

首次部署合同

private stocks: UnorderedMap<number> = new UnorderedMap<number>('prefix1');

constructor() {
  this.stocks.set('msft', 10);
}

@call({})
buy(): number {
  const stock: string = 'msft';
  return this.stocks.get(stock); // 将返回 10
}

在添加新的股票对象后再次部署合同

private stocks: UnorderedMap<number> = new UnorderedMap<number>('prefix1');
private superStocks: UnorderedMap<number> = new UnorderedMap<number>('prefix2'); // 当我们重新部署合同时不会被初始化  

constructor() {
  this.stocks.set('msft', 10);
  this.superStocks.set('msft', 20); // 如果我们重新部署到同一地址,将永远不会调用这个
}

@call({})
buy(): number {
  const stock: string = 'msft';
  return this.superStocks.get(stock); // 错误。无法读取未定义的属性'prefix'
}

已经部署的智能合约如果您重新部署它(在同一地址上)将不会再次调用构造函数。构造函数仅在首次部署时调用。

如果我获取您当前的智能合约代码,构建并部署它,我可以调用buy函数而不会出错。

如何修复?

我唯一能够解决这个问题的方法是将合同部署到一个新的地址。我认为这是near-sdk-js的问题,并且我已经在GitHub存储库中提交了一个问题: https://github.com/near/near-sdk-js/issues/358

英文:

This most likely happens because you have made changes to your smart-contract since the first time you deployed it. You can then end up accessing an object that hasn't been defined yet. This can happen if you try to initialize additional objects after having deployed the contract once already.

For example

Deploy the contract for the first time

private stocks: UnorderedMap&lt;number&gt; = new UnorderedMap&lt;number&gt;(&#39;prefix1&#39;);

constructor() {
  this.stocks.set(&#39;msft&#39;, 10);
}

@call({})
buy(): number {
  const stock: string = &#39;msft&#39;;
  return this.stocks.get(stock); // will return 10
}

Deploy the contract again after adding a new stocks object

private stocks: UnorderedMap&lt;number&gt; = new UnorderedMap&lt;number&gt;(&#39;prefix1&#39;);
private superStocks: UnorderedMap&lt;number&gt; = new UnorderedMap&lt;number&gt;(&#39;prefix2&#39;); // will not be initialized when we re-deploy the contract  

constructor() {
  this.stocks.set(&#39;msft&#39;, 10);
  this.superStocks.set(&#39;msft&#39;, 20); // this will never be called if we re-deploy to the same address
}

@call({})
buy(): number {
  const stock: string = &#39;msft&#39;;
  return this.superStocks.get(stock); // Opps. Cannot read property &#39;prefix&#39; of undefined\n
}

A smart-contract that is already deployed will not call the constructor again if you re-deploy it (on the same address.) The constructor is only called on the first deploy.

If I take your current smart-contract code, build and deploy it, I'm able to call the buy function without getting an error.

How to fix it?

The only way I was able to fix the issue was to deploy the contract to a new address. I believe this is an issue with near-sdk-js, and I've submitted an issue to the GitHub repo: https://github.com/near/near-sdk-js/issues/358

huangapple
  • 本文由 发表于 2023年6月27日 20:49:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76565036.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定