[Stack]: RuntimeError: memory access out of bounds error while testing a function in a NEAR protocol smart contract assemblyscript - nearprotocol

I get this error on running the test function in my NEAR protocol:
[Stack]: RuntimeError: memory access out of bounds
Here is my test function:
describe("Main Flow", () => {
it('Tests the flow of the app', () => {
setContext('hamzatest.testnet', u128.from(0));
const service1 = contract.addService('gloriajeans.testnet', 'Gloria Jeans', 'Free Coffee', '2023-07-10T15:00:00.000');
}); });
Here is the function:
#mutateState()
addService(provider: string, title: string, description: string, expiryDate: string): Service {
let expiryDateTimestamp: u64 = Date.fromString(expiryDate).getTime();
let currentTime: u64 = this._toMillisecond(context.blockTimestamp);
assert(expiryDateTimestamp > currentTime, Constants.INVALID_EXPIRY_DATE);
let id = (provider + '/' + currentTime.toString()).toUpperCase();
let service = new Service(
id,
provider,
title,
description,
0,
currentTime,
expiryDateTimestamp
);
this.services.set(id, service);
this.services_ids.push(id);
return service;
}
Any idea why?

Related

Signature verification failed

Please help, when executing this function, an error about the signature comes out
export const UseMetaplexProvider = () => {
const { connection } = useConnection();
const wallet = useWallet();
return useMemo(
() =>
Metaplex.make(solanaConnection)
.use(walletAdapterIdentity(wallet))
.use(
bundlrStorage({
address: "https://devnet.bundlr.network",
// providerUrl: endpoint,
timeout: 60000,
})
),
[solanaConnection, wallet]
);
};
const { uri } = await metaplex.nfts().uploadMetadata({
name: "Test Token",
symbol: "TEST",
description: "This is a test token!",
image:
"https://bipbap.ru/wp-content/uploads/2017/04/0_7c779_5df17311_orig.jpg", //add public URL to image you'd like to use
});
console.log("URI", uri);
console.log("METADATA", metadata);
I tried using metaplex.identity().signMessage(). But it still didn't help

How to get unique smart contract errors in a frontend app using polkadot.js

I am implementing a smart contract with ink!
I have defined my own errors in the smart contract like the example below.
I don't know how to get the error information in my frontend app using polkadot.js when this error occurs.
Can anyone tell me who knows?
smart contract sample:
-- snip --
#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum OwnErrors {
/// The Token Does Not Exists.
OwnErrorIsOccured,
}
-- snip --
#[ink(message)]
pub fn own_error_test(&mut self, account_id:AccountId, token_type:u8) -> OwnResult<()> {
if self.value == false {
return Err(OwnErrors::OwnErrorIsOccured);
}
self.token_list_for_id.insert(&self.next_id, &TokenInfo{token_address:account_id,token_type:TokenType::GovernanceToken});
self.next_id = self.next_id + 1;
Ok(())
}
-- snip --
frontend sample:
-- snip --
const own_error_test = async () => {
const { web3FromSource } = await import("#polkadot/extension-dapp");
const contract = new ContractPromise(api, abi, contractAddress);
const performingAccount = accounts[0];
const injector = await web3FromSource(performingAccount.meta.source);
const flip = await contract.tx.ownErrorTest(
{ value: 0, gasLimit: gasLimit },
actingAddress,
0
);
if (injector !== undefined) {
flip.signAndSend(actingAddress, { signer: injector.signer }, (result) => {
if (result.status.isInBlock) {
setResult("in a block");
} else if (result.status.isFinalized) {
setResult("finalized");
}
console.log("###result: ",result);
});
}
};
-- snip --
I got the answer on Astar Network's Discord.
https://substrate.stackexchange.com/questions/4247/how-to-get-output-when-calling-a-contract-method-and-signing-it/4261#4261
pub enum OwnErrors {
/// The Token Does Not Exists.
OwnErrorIsOccured,
}
if ( output?.toHuman()?.Err == "OwnErrorIsOccured"){
alert("I can handle errors");
return;
}

Handle unsubscribe GraphQL subscription

I have an issue with subscription can't be unsubscribe.
Before we start, this is my setup: Apollo Client(graphql-ws) <-> Apollo Server(graphql-ws). On the server, I build a custom PubSub instead of using the one provided.
As you can see here, the client has sent a complete request to server with the id. However, the server is still sending more data to it. I have read somewhere that you have to send GQL_STOP, aka STOP instead. However, this is what Apollo Client is sending.
A bit of code:
Client subscription:
export const useGetDataThroughSubscription = (
resourceIds: number[],
startDate?: Date,
endDate?: Date
) => {
const variables = {
startTime: startDate?.toISOString() ?? '',
endTime: endDate?.toISOString() ?? '',
resourceIds,
};
return useGetDataSubscription({
variables,
...
})
}
Server pubsub:
const createPubSub = <TopicPayload extends { [key: string]: unknown }>(
emitter: EventEmitter = new EventEmitter()
) => ({
publish: <Topic extends Extract<keyof TopicPayload, string>>(
topic: Topic,
payload: TopicPayload[Topic]
) => {
emitter.emit(topic as string, payload);
},
async *subscribe<Topic extends Extract<keyof TopicPayload, string>>(
topic: Topic,
retrievalFunc: (value: TopicPayload[Topic]) => Promise<any>
): AsyncIterableIterator<TopicPayload[Topic]> {
const asyncIterator = on(emitter, topic);
for await (const [value] of asyncIterator) {
const data = await retrievalFunc(value);
yield data;
}
},
Server subscribe to event:
const resolver: Resolvers = {
Subscription: {
[onGetAllLocationsEvent]: {
async *subscribe(_a, _b, ctx) {
const locations = await ...;
yield locations;
const iterator = ctx.pubsub.subscribe(
onGetAllLocationsEvent,
async (id: number) => {
const location = ...;
return location;
}
);
for await (const data of iterator) {
if (data) {
yield [data];
}
}
},
resolve: (payload) => payload,
},
},
};
In this one, if instead of the for loop, I return iterator instead, then the server will send back a complete and stop the subscription all together. That's great, but I want to keep the connection open until client stop listening.
And server publish
ctx.pubsub.publish(onGetAllResourcesEvent, resource.id);
So how should I deal with this?

Error: call revert exception on Hardhat with Mocha,Chai,Waffle Testing when calling a getter with Contract.connect(Signer)

While testing some code on hardhat, I found an unexplained exception that was being thrown. I couldn't find any solution both on the discord channels, as well as in the etherjs docs.
This is my test suite:
import {ethers} from "hardhat";
import {loadFixture} from "ethereum-waffle";
describe.only("Images", async function () {
let result;
it("Creates images", async function () {
const {Decentragram} = await loadFixture(fixture);
const [owner, address2] = await ethers.getSigners();
result = await Decentragram.connect(owner).uploadImage();
let test = await Decentragram.connect(owner).test("test");
console.log(test);
});
});
This is my contract:
pragma solidity 0.8.6;
contract Decentragram {
string public name = "Decentragram";
// Store Images
mapping(uint256 => Image) public images;
mapping(string => uint256) public test;
struct Image {
uint256 id;
string hashImg;
string description;
uint256 tipAmount;
address payable author;
}
// Create Images
function uploadImage() public {
images[1] = Image({
id: 1,
hashImg: "abcd",
description: "description",
tipAmount: 0,
author: payable(address(0x0))
});
}
function getImage(uint256 id) public view returns (Image memory) {
Image memory img = images[id];
return img;
}
// Tip Images
}
This is the error I'm getting when running "npx hardhat test":
Error: call revert exception (method="test(string)", errorArgs=null, errorName=null, errorSignature=null, reason=null, code=CALL_EXCEPTION, version=abi/5.4.0)
at Logger.makeError (node_modules\#ethersproject\logger\src.ts\index.ts:213:28)
at Logger.throwError (node_modules\#ethersproject\logger\src.ts\index.ts:225:20)
at Interface.decodeFunctionResult (node_modules\#ethersproject\abi\src.ts\interface.ts:425:23)
at Contract.<anonymous> (node_modules\#ethersproject\contracts\src.ts\index.ts:332:44)
at step (node_modules\#ethersproject\contracts\lib\index.js:48:23)
at Object.next (node_modules\#ethersproject\contracts\lib\index.js:29:53)
at fulfilled (node_modules\#ethersproject\contracts\lib\index.js:20:58)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at runNextTicks (internal/process/task_queues.js:64:3)
at listOnTimeout (internal/timers.js:526:9)
at processTimers (internal/timers.js:500:7)
In the test suite:
import {ethers} from "hardhat";
import {loadFixture} from "ethereum-waffle";
describe.only("Images", async function () {
let result;
it("Creates images", async function () {
const {Decentragram} = await loadFixture(fixture);
const [owner, address2] = await ethers.getSigners();
result = await Decentragram.connect(owner).uploadImage();
let test = await Decentragram.test("test"); <<<<< don't use .connect() in order to call any default getter generated by solidity. Can't tell for sure but perhaps is because it is not necessary. There's not msg.sender on the call? Who knows? If you do, i'd appreciate your explanation below.
console.log(test);
});
});
I finally found the explanation. Turns out when I deployed my contract I used this fixture on mocha-waffle:
Here, when the contract gets deployed it's already tied to a signer (owner).
async function fixture([owner]: Wallet[], provider: Provider) {
const _Decentragram: Contract = await deployContract(owner, DecentragramJSON);
const Decentragram: Contract = await _Decentragram.deployed();
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Here we instead use a contract factory deploy method, which doesn't need a Signer by default.
const _Decentagram2Fac = await ethers.getContractFactory("Decentragram");
const _Decentagram2 = await _Decentagram2Fac.deploy();
const Decentragram2 = await _Decentagram2.deployed();
return {Decentragram, Decentragram2};
}

Truffle tests not working, recieving: VM Exception while processing transaction: out of gas

I'm trying to test my contract but I'm receiving this error:
Events
✔ deploys a factory and an event
✔ marks caller as the event manager
1) allows the user to buy a ticket and stores their details
2 passing (1s)
1 failing
1) Events
allows the user to buy a ticket and stores their details:
c: VM Exception while processing transaction: out of gas
at Function.c.fromResults (node_modules/ganache-cli/build/ganache-core.node.cli.js:4:192416)
at w.processBlock (node_modules/ganache-cli/build/ganache-core.node.cli.js:42:50915)
at processTicksAndRejections (internal/process/task_queues.js:94:5)
However, when looking over my code I believe I have more than enough gas and perhaps this error has to do with something else.
Here is the code for my test:
const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider({ gasLimit: 10000000 }));
const compiledFactory = require("../ethereum/build/EventFactory.json");
const compiledCampaign = require("../ethereum/build/Event.json");
let accounts;
let factory;
let eventAddress;
let event;
beforeEach(async () => {
accounts = await web3.eth.getAccounts();
factory = await new web3.eth.Contract(JSON.parse(compiledFactory.interface))
.deploy({ data: compiledFactory.bytecode })
.send({ from: accounts[0], gas: "10000000" });
await factory.methods.createEvent("test event", 2, 1, "Elton John's world tour", "Faketown auditorium", 100).send({
from: accounts[0],
gas: "10000000",
});
[eventAddress] = await factory.methods.getDeployedEvents().call();
event = await new web3.eth.Contract(
JSON.parse(compiledCampaign.interface),
eventAddress
);
});
describe("Events", () => {
it("deploys a factory and an event", () => {
assert.ok(factory.options.address);
assert.ok(event.options.address);
});
it("marks caller as the event manager", async () => {
const manager = await event.methods.manager().call();
assert.equal(accounts[0], manager);
});
it("allows the user to buy a ticket and stores their details", async () => {
await event.methods.buyTicket('Louie').send({
value: '1',
from: accounts[1]
});
const isContributor = await event.methods.attendees(account[1]).call();
assert(isContributor);
});
});
As you can see, my first two tests pass. However the third does not work. I believe I am providing enough gas. Here is my contract so you can look at the functions:
pragma solidity ^0.4.17;
contract EventFactory {
address[] public deployedEvents;
function createEvent(string title, uint max, uint cost, string description, string location, uint date) public {
address newEvent = new Event(title, msg.sender, max, cost, description, location, date);
deployedEvents.push(newEvent);
}
function getDeployedEvents() public view returns (address[]) {
return deployedEvents;
}
}
contract Event {
struct Attendee {
bool valid;
string name;
uint ticketNumber;
bool confirmed;
uint amountPaid;
uint confirmationCode;
}
address public manager;
string public title;
uint public maxAttendees;
uint public ticketsSold;
mapping(address=>Attendee) public attendees;
uint public ticketCost;
string public eventDescription;
string public eventLocation;
uint public eventDate;
mapping(address=>bool) public blacklist;
modifier restricted() {
require(msg.sender == manager);
_;
}
function random(uint seed) private view returns (uint) {
uint tmp = uint(block.blockhash(block.number - 1));
return uint(keccak256(tmp,seed)) % 1000000000;
}
function Event(string eventTitle, address creator, uint max, uint cost, string description, string location, uint date) public {
title = eventTitle;
manager = creator;
maxAttendees = max;
ticketsSold = 0;
ticketCost = cost;
eventDescription = description;
eventLocation = location;
eventDate = date;
}
function buyTicket(string name) public payable {
require(blacklist[msg.sender] != true);
require(ticketsSold != maxAttendees);
require(attendees[msg.sender].valid == false);
require(msg.value == ticketCost);
Attendee memory attendee = Attendee({
valid: true,
name: name,
ticketNumber: (maxAttendees - ticketsSold),
confirmed: false,
amountPaid: ticketCost,
confirmationCode: 0
});
ticketsSold++;
attendees[msg.sender] = attendee;
}
function challengeAttendee(address attendee, uint seed) public restricted returns (uint) {
require(attendees[attendee].valid == true);
uint code = random(seed);
attendees[attendee].confirmationCode = code;
return code;
}
function confirmTicketOwnerShip(uint code) public {
require(attendees[msg.sender].confirmationCode != 0);
attendees[msg.sender].confirmed = attendees[msg.sender].confirmationCode == code;
}
function confirmResponse(address attendee) public restricted view returns (bool) {
return attendees[attendee].confirmed;
}
function addToBlackList(address blockedAddress) public restricted {
blacklist[blockedAddress] = true;
}
function getEventDetails() public view returns (string, uint, uint, uint, string, string, uint) {
return (
title,
maxAttendees,
ticketsSold,
ticketCost,
eventDescription,
eventLocation,
eventDate
);
}
}
Try replacing this test:
it("allows the user to buy a ticket and stores their details", async () => {
await event.methods.buyTicket('Louie').send({
value: '1',
from: accounts[1]
});
const isContributor = await event.methods.attendees(account[1]).call();
assert(isContributor);
});
with the following one:
it("allows the user to buy a ticket and stores their details", async () => {
await event.methods.buyTicket('Louie').send({
value: '1',
gasPrice: '1',
from: accounts[1]
});
const isContributor = await event.methods.attendees(account[1]).call();
assert(isContributor);
});
I've found the error, unfortunately, it's simply a typo. On the sixth line down I use account[1] not accounts[1]. Also I had to specify the gas as the default amount was not enough.
My code now looks like:
it("allows the user to buy a ticket and stores their details", async () => {
await event.methods.buyTicket("Louie").send({
from: accounts[1],
value: '1',
gas: '20000000'
});
const isContributor = await event.methods.attendees(accounts[1]).call();
assert(isContributor.valid);
});

Resources