Getting a gas estimation error when trying to interact with contract on remix - bots

So i am trying to make a bot that will automatically swap from token 1 to token 2 back to token 1 continously until the balance of one token in my wallet decreases by 10%. So now i am trying to test this on Goeril test-net where i have deployed the Multiswap Smart contract that will do the swap.
i created 2 tokens USDCS and DAIS so i can simulate DAI/USDC pair from main-net.
pragma solidity =0.7.6;
pragma abicoder v2;
import "#uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
import "#uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
contract SwapExamples {
// NOTE: Does not work with SwapRouter02
ISwapRouter public constant swapRouter =
ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
address public constant DAIS = 0xe064A598C2254911a25dFc028719B8efCCFF4C87;
address public constant USDCS = 0x7f1B888970CB35baE87a1C26eB6D7b0e0Dfbded8;
/// #notice swapInputMultiplePools swaps a fixed amount of WETH for a maximum possible amount of DAI
/// swap USDC --> DAI --> USDC
function swapExactInputMultihop(uint amountIn)
external
returns (uint amountOut)
{
TransferHelper.safeTransferFrom(
DAIS,
msg.sender,
address(this),
amountIn
);
TransferHelper.safeApprove(DAIS, address(swapRouter), amountIn);
ISwapRouter.ExactInputParams memory params = ISwapRouter
.ExactInputParams({
path: abi.encodePacked(
DAIS,
uint24(500),
USDCS,
uint24(500),
DAIS
),
recipient: msg.sender,
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: 0
});
amountOut = swapRouter.exactInput(params);
}
}
when i interact with this contract using remix after deploying it successfully, i get this unexpected gas error message.
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
execution reverted: STF { "originalError": { "code": 3, "data": "0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000035354460000000000000000000000000000000000000000000000000000000000", "message": "execution reverted: STF" } }
i try to swap 1000 DAIS and there are 250 million of DAIS and USDCS each.
What could be the issue ?
is it the approval
I tried putting an approval of the 1000 tokens first.
mapping(address => mapping (address => uint256)) allowed;
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
function approve(address delegate, uint256 numTokens) public returns (bool) {
allowed[msg.sender][delegate] = numTokens;
emit Approval(msg.sender, delegate, numTokens);
return true;
}
but i still get the same error

Related

NEAR PROTOCOL FunctionCallError(HostError(GasLimitExceeded)) Error when I recover more than 150 tokens

I'm developing a pagination method, but when the number of tokens pass over the 150, return this error: FunctionCallError(HostError(GasLimitExceeded))
The command that I used:
near view nativodeploy.testnet get_ids_onsale '{"tokens":30}' --accountId nativodeploy.testnet
Code: Here I only recover a vector with the Id tokens that I use to initiate the "from_index" in another method
pub fn get_ids_onsale(&self,tokens:u64) -> Vec<u64> {
let mut vectIDs = vec![];
let mut _tokfound =0;
let total = self.get_on_total_toks();
vectIDs.push(0);
for x in 0..total {
if x>= total.clone() {
break;
}
let mut token =self.get_token(x.to_string().clone());
if token.on_sale{
_tokfound+=1;
if _tokfound== tokens {
vectIDs.push( token.token_id.parse::<u64>().unwrap() );
_tokfound=0;
}
}
if( _tokfound == tokens ){break; }
}
vectIDs
}
If I use a call I get this:
{"ExecutionError":"Exceeded the prepaid gas."}
Even if I use the --gas=300000000000000, I get this:
{"ExecutionError":"Exceeded the maximum amount of gas allowed to burn per contract."}
you are limited to 200 Tgas for each function call and can only attach 300 Tgas total (extra gas added for cross-contract calls) based on a limit in near-api-js iirc.
so you will have to return fewer than 150 results.
this number will be lower if each record you return is larger of course
it's about the amount of data you are reading from storage and what you do with it.
you can read more about gas here:
https://docs.near.org/docs/concepts/gas

HazelcastJet kafka throttling

I couldn't find any possibilities to create pipeline in hazelcast-jet-kafka that will limit the throughput to a specific number of elements per time unit, anybody could suggest me possible solutions? I know that alpaka (https://doc.akka.io/docs/alpakka-kafka/current/) has such functionality
You can define this function:
private <T, S extends GeneralStage<T>> FunctionEx<S, S> throttle(int itemsPerSecond) {
// context for the mapUsingService stage
class Service {
final int ratePerSecond;
final TreeMap<Long, Long> counts = new TreeMap<>();
public Service(int ratePerSecond) {
this.ratePerSecond = ratePerSecond;
}
}
// factory for the service
ServiceFactory<?, Service> serviceFactory = ServiceFactories
.nonSharedService(procCtx ->
// divide the count for the actual number of processors we have
new Service(Math.max(1, itemsPerSecond / procCtx.totalParallelism())))
// non-cooperative is needed because we sleep in the mapping function
.toNonCooperative();
return stage -> (S) stage
.mapUsingService(serviceFactory,
(ctx, item) -> {
// current time in 10ths of a second
long now = System.nanoTime() / 100_000_000;
// include this item in the counts
ctx.counts.merge(now, 1L, Long::sum);
// clear items emitted more than second ago
ctx.counts.headMap(now - 10, true).clear();
long countInLastSecond =
ctx.counts.values().stream().mapToLong(Long::longValue).sum();
// if we emitted too many items, sleep a while
if (countInLastSecond > ctx.ratePerSecond) {
Thread.sleep(
(countInLastSecond - ctx.ratePerSecond) * 1000/ctx.ratePerSecond);
}
// now we can pass the item on
return item;
}
);
}
Then use it to throttle in the pipeline:
Pipeline p = Pipeline.create();
p.readFrom(TestSources.items(IntStream.range(0, 2_000).boxed().toArray(Integer[]::new)))
.apply(throttle(100))
.writeTo(Sinks.noop());
The above job will take about 20 seconds to complete because it has 2000 items and the rate is limited to 100 items/s. The rate is evaluated over the last second, so if there are less than 100 items/s, items will be forwarded immediately. If there are 101 items during one millisecond, 100 will be forwarded immediately and the next after a sleep.
Also make sure that your source is distributed. The rate is divided by the number of processors in the cluster and if your source isn't distributed and some members don't see any data, your overall rate will be only a fraction of the desired rate.

Getting Error: http: read on closed response body from Transaction Processor function in Hyperledger Composer

I've a fabric network running with a simple BNA. This BNA defines two types of participants viz. Corporate and Person. Here, each Person has a relationship with the corporate as shown below (cto file):
participant Corporate identified by corporateId {
o String corporateId
o String corporateName
}
participant Person identified by personId {
o String personId
--> Corporate corporate
}
What I'm trying to do:
Create a Corporate using Transaction Processor Function: Success
Create a Person using Transaction Processor Function: Failure
Following is the snippet from transaction processor function for #2:
let corporateIdExpected = personDetails.corporate;
if(corporateIdExpected && corporateIdExpected != '') {
let corporateRetrieved = await query("GetCorporateByCorporateId", {corporateId: corporateIdExpected});
if(!corporateRetrieved || corporateRetrieved == '') {
throw new Error("Corporate details not valid. Please check if your corporate is present on the network.");
}
}
Snippet from my queries.qry:
query GetCorporateByCorporateId {
description: "Returns all corporates in the registry"
statement:
SELECT org.samplenetwork.participants.Corporate
WHERE (corporateId == _$corporateId)
}
So, I get the following error when I try the #2:
Error: 2 UNKNOWN: error executing chaincode: transaction returned with failure: Error: Error: http: read on closed response body
However, when I try to execute the query directly from the swagger, it runs successfully.
I'm using:
Hyperledger Fabric: 1.1
Hyperledger Composer: 0.19.8
Am I missing out any checks or steps for this one?
for item 2 - you don't really need to execute a named query each time.
You can do the equivalent check ("does he exist already?") as follows (where trxn below is the transaction object defined in your transaction definition etc):
const personRegistry = await getParticipantRegistry('org.acme.example.Person');
console.log("The person identifier to check is " + trxn.corporate.getIdentifier() )
const exists = await personRegistry.exists(trxn.corporate.getIdentifier() ) ;
console.log("exists is set to " + exists); // boolean
if (exists)
console.log("he exists")
else
console.log("he doesn't exist");

Error when submitting transaction

I have a little bit unusual problem. Following code works in online playground, but id doesn't work when i'm using generated API on rest server deployed locally. When trying to post transaction i get an error.
cto file:
namespace org.dps.track
asset Item identified by itemId{
o String itemId
o String name
o String idgId
o String serialNumber
o String comment
--> BU owner
--> Item [] items optional
}
participant BU identified by buId{
o String buId
o String name
o String country
o String city
}
participant Assembler extends BU{
}
participant Manufacturer extends BU{
}
transaction Trade{
--> Item item
--> BU newOwner
}
enum status{
o IN_TRANSIT
o DEPARTURED
o DELIVERED
}
chaincode:
/**
* Sample transaction processor function.
* #param {org.dps.track.Trade } trade - the sample transaction instance.
* #transaction
*/
async function tradeCommodity(trade) {
const factory = getFactory();
trade.item.owner = trade.newOwner;
var list = [];
if (trade.item.items && trade.item.items.length > 0) {
trade.item.items.forEach((asset) => {
list.push(asset);
});
}
const assetRegistry = await getAssetRegistry('org.dps.track.Item');
// persist the state of the current ITEM
await assetRegistry.update(trade.item);
for (var i = 0; i < list.length; ++i) {
let res = await assetRegistry.get(list[i].getIdentifier());
res.owner = factory.newRelationship('org.dps.track', 'Assembler', trade.newOwner.getIdentifier());
// persist the state of the ITEM with new owner as a relationship
await assetRegistry.update(res);
}
}
When trying to post transaction via Rest API i get error:
{
"error": {
"statusCode": 500,
"name": "Error",
"message": "Error trying invoke business network. Error: No valid responses from any peers.\nResponse from attempted peer comms was an error: Error: transaction returned with failure: Error: Could not find any functions to execute for transaction org.dps.track.Trade#e4764be8e037c7186774512860c0cde6d7eaed5c301ddf36c4c1ab560577861a",
"stack": "Error: Error trying invoke business network. Error: No valid responses from any peers.\nResponse from attempted peer comms was an error: Error: transaction returned with failure: Error: Could not find any functions to execute for transaction org.dps.track.Trade#e4764be8e037c7186774512860c0cde6d7eaed5c301ddf36c4c1ab560577861a\n at HLFConnection.invokeChainCode (/home/bryczek/.nvm/versions/node/v8.11.3/lib/node_modules/composer-rest-server/node_modules/composer-connector-hlfv1/lib/hlfconnection.js:1002:30)\n at <anonymous>"
}
}
Has anyone an idea what is wrong? I would be really thankful for help.
Your problem is your model file, not the transaction code. You need Assembler not BU in the relationship field for Item and for Trade
Your asset should be:
asset Item identified by itemId{
o String itemId
o String name
o String idgId
o String serialNumber
o String comment
--> Assembler owner
--> Item [] items optional
}
as Assembler is the resource class (not BU, which is an extended class - there is no registry for this).
Your transaction Trade should also reflect the same resource ie (not BU) :
transaction Trade{
--> Item item
--> Assembler newOwner
}
Other than that, it should work fine with your existing code (have tested it against a Fabric network, using the following example Trade transaction in my REST API, where previous owner was Assembler#1 and it changes related Items from the items array for Item #1)
{
"$class": "org.dps.track.Trade",
"item":"resource:org.dps.track.Item#1",
"newOwner":"resource:org.dps.track.Assembler#2"
}
I modified model file and now whe n trying to generate rest API i only get System(General business network methods), no Item, BU and Trade API, why is this happening?
cto:
/**
* New model file
*/
namespace org.dps.track
//asset section
asset Item identified by itemId{
o String itemId
o String name
o String idgId
o String serialNumber
o String comment
--> BU owner
--> Item [] items optional
}
//participant section
participant BU identified by buId{
o String buId
o String name
o String country
o String city
o participantType type
}
//tranasaction section
transaction Trade{
-->Item item
-->BU newOwner
}
enum status {
o IN_TRANSIT
o DEPARTURED
o DELIVERED
}
enum participantType{
o Manufacturer
o Assembler
}
cc:
/**
* Sample transaction processor function.
* #param {org.dps.track.Trade } trade - the sample transaction instance.
* #transaction
*/
async function tradeCommodity(trade) {
const factory = getFactory();
trade.item.owner = trade.newOwner;
var list = [];
if (trade.item.items && trade.item.items.length > 0) {
trade.item.items.forEach((asset) => {
list.push(asset);
});
}
const assetRegistry = await getAssetRegistry('org.dps.track.Item');
// persist the state of the current ITEM
await assetRegistry.update(trade.item);
for (var i = 0; i < list.length; ++i) {
let res = await assetRegistry.get(list[i].getIdentifier());
res.owner = factory.newRelationship('org.dps.track', 'BU', trade.newOwner.getIdentifier());
// persist the state of the ITEM with new owner as a relationship
await assetRegistry.update(res);
}
}

Hyperledger Composer - ACL Rule with function in condition

I'm trying to write a little complexer logic in the condition of an ACL Rule as always the p.getIdentifier() == r.getIdentifier(), because in my fault it isn't possible.
These are my models:
participant Customer identified by customerID {
o String customerID
o String name
...
}
asset A identified by aID {
o String aID
--> Customer customer
}
asset B identified by bID {
o String bID
--> A a
}
Now I want to give the Customer access to see all B assets, but only where the relationship to A references to an asset, which have a relatinship to the actual participant of Customer, who is "logged in".
Summarized logic: From asset B to A, and then from A to Customer.
So in this case I can't compare the identifiers of Customer and B directly and have to go over A. Therefore I wanted to evaulate the access with a function which is called in the script.js file:
rule CustomerAccessCustomer {
description: "The customer should see all B assets, but only when he have a relationship in asset A "
participant(p): "org.xxx.test.participant.Customer"
operation: READ
resource(r): "org.xxx.test.asset.B"
condition: (evaluateAccess(p,r))
action: ALLOW
}
Here is the function of the script.js:
async function evaluateAccess(p,r) {
try {
const bRegistry = await getAssetRegistry('org.xxx.test.asset.B');
const b = await bRegistry.get(r.getIdentifier());
const aRegistry = await getAssetRegistry('org.xxx.test.asset.A');
const a = await aRegistry.get(b.a.getIdentifier());
if (p.getIdentifier() === a.customer.getIdentifier()) {
return true;
}
} catch (error) {
console.log(error);
}
}
But I get an error Error: The runtime API is not available.
Do I think the wrong way, isn't it possible to evaluate access with a function?
How did you handle access rule if you can't just compare the identifiers?
you should just be able to do:
rule CustomerAccessCustomer {
description: "The customer should see all B assets, but only when he have a relationship in asset A "
participant(p): "org.xxx.test.participant.Customer"
operation: READ
resource(r): "org.xxx.test.asset.B"
condition: ( (p.getIdentifier() === r.a.customer.getIdentifier())
action: ALLOW
}
but p would also need READ access already to be able to 'read' Asset resource 'A' (to check the identifier etc) in the first place :-)
The customer should be participant not asset:
participant Customer identified by customerID {
o String customerID
o String name
}

Resources