Fail with error 'PancakeLibrary: INSUFFICIENT_AMOUNT' - javascript

I'm trying to fork PANCAKESWAP, everything seem to work well, I can add liquidity, but whenever I decided to add a liquidity that has to do with BNB (i.e calling the addLiquidityETH function) transaction gets reverted with that error message.
After a little digging, I found out it only appears in a single place in the whole router.
// given some amount of an asset and pair reserves, returns an equivalent amount of the other asset
function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) {
require(amountA > 0, 'PancakeLibrary: INSUFFICIENT_AMOUNT'); // THIS IS WHERE TRIGGERS THE REVERT!!
require(reserveA > 0 && reserveB > 0, 'PancakeLibrary: INSUFFICIENT_LIQUIDITY');
amountB = amountA.mul(reserveB) / reserveA;
}
and this quote function got called in the _addLiquidity function as seen below.
// **** ADD LIQUIDITY ****
function _addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin
) internal virtual returns (uint amountA, uint amountB) {
// create the pair if it doesn't exist yet
if (IPancakeFactory(factory).getPair(tokenA, tokenB) == address(0)) {
IPancakeFactory(factory).createPair(tokenA, tokenB);
}
(uint reserveA, uint reserveB) = PancakeLibrary.getReserves(factory, tokenA, tokenB);
if (reserveA == 0 && reserveB == 0) {
(amountA, amountB) = (amountADesired, amountBDesired);
} else {
uint amountBOptimal = PancakeLibrary.quote(amountADesired, reserveA, reserveB); // here calls the quote function
if (amountBOptimal <= amountBDesired) {
require(amountBOptimal >= amountBMin, 'PancakeRouter: INSUFFICIENT_B_AMOUNT');
(amountA, amountB) = (amountADesired, amountBOptimal);
} else {
uint amountAOptimal = PancakeLibrary.quote(amountBDesired, reserveB, reserveA); // and here too
assert(amountAOptimal <= amountADesired);
require(amountAOptimal >= amountAMin, 'PancakeRouter: INSUFFICIENT_A_AMOUNT');
(amountA, amountB) = (amountAOptimal, amountBDesired);
}
}
}
So far, these are the ONLY places that calls quote which will result to the transaction getting reverted, but I can't seem to find anything wrong I mean, AmountA is obviously > 0.
Any help would be really appreciated.
EDIT:
The error was from my end, I was debugging an old transaction where I didn't send BNB to the contract, and I assumed it was the same error I received for the future transaction, decided to check and found out the error I was receiving was INSUFFICIENT_A_AMOUNT, fixed it by setting amountETHMin and amountTokenMin to 0

The error was from my end, I was debugging an old transaction where I didn't send BNB to the contract, and I assumed it was the same error I received for the future transaction, decided to check and found out the error I was receiving was INSUFFICIENT_A_AMOUNT, fixed it by setting amountETHMin and amountTokenMin to 0

I've met this error, this is the demo java code to fix the bug.
raw = RawTransaction.createTransaction(
nonce,
gasProvider.getGasPrice(),
gasProvider.gasLimit,
contractAddress,
amountEth.toWei(), //>>> add amount of bnb here, when create rawTransaction
FunctionEncoder.encode(function)
)
rawTransactionManager.signAndSend(raw)

Related

Make Web MIDI API listen to a specific channel

I am making a proyect where I'm using the web MIDI API and a loopback MIDI port, but I want to know if there is any way tomakeit listen to different channel other than the first?
Here is my code:
var notes=[]
navigator.requestMIDIAccess()
.then(onMIDISuccess, onMIDIFailure);
function onMIDISuccess(midiAccess) {
for (var input of midiAccess.inputs.values()){
input.onmidimessage = getMIDIMessage;
}
}
function getMIDIMessage(message) {
var command = message.data[0];
var note = message.data[1];
var velocity = (message.data.length > 2) ? message.data[2] : 0; // a velocity value might not be included with a noteOff command
console.log(message)
switch (command) {
case 144: // noteOn
if (velocity > 0) {
noteOn(note, velocity);
} else {
noteOff(note);
}
break;
case 128: // noteOff
noteOff(note);
break;
}
}
function onMIDIFailure() {
console.log('Could not access your MIDI devices.');
}
Also, I haven't seen any property in the MIDI messages related to the channels, so I really don't know how to do it.
The channel is encoded in the first byte. If the value is 144 it means the message is for the first channel. A value of 145 would be for the second channel. Up to 159 which is a note on message for the 16th channel.
The same principle applies to note off messages. A value of 128 is for the first channel. A value of 129 is for the second channel. ...
You can get the index of the channel with a binary operation like this:
const channelIndex = message.data[0] & 0x0F;
The type of event can be checked by shifting the value by four bits.
const eventType = message.data[0] >> 4;
A value of 8 would be a note off message. A value of 9 is a note on message.

Encoding -1 as a uint256

As per Aave documentation for liquidationCall one must pass uint(-1) for debtToCover parameter in order to liquidate the maximum amount possible for an account with a healthFactor < 1. How is it possible to encode -1 as a uint256 using web3, ethers, etc?
Attempting this using web3, for example yields an error.
> web3.eth.abi.encodeParameter("uint", "-1")
Uncaught:
Error: value out-of-bounds (argument=null, value="-1", code=INVALID_ARGUMENT, version=abi/5.0.7)
at Logger.makeError (-/node_modules/#ethersproject/logger/lib/index.js:199:21)
at Logger.throwError (-/node_modules/#ethersproject/logger/lib/index.js:208:20)
at Logger.throwArgumentError (-/node_modules/#ethersproject/logger/lib/index.js:211:21)
at NumberCoder.Coder._throwError (-/node_modules/web3-eth-abi/node_modules/#ethersproject/abi/lib/coders/abstract-coder.js:40:16)
at NumberCoder.encode (-/node_modules/web3-eth-abi/node_modules/#ethersproject/abi/lib/coders/number.js:40:18)
at -/node_modules/web3-eth-abi/node_modules/#ethersproject/abi/lib/coders/array.js:71:19
at Array.forEach (<anonymous>)
at Object.pack (-/node_modules/web3-eth-abi/node_modules/#ethersproject/abi/lib/coders/array.js:57:12)
at TupleCoder.encode (-/node_modules/web3-eth-abi/node_modules/#ethersproject/abi/lib/coders/tuple.js:36:24)
at AbiCoder.encode (-/node_modules/web3-eth-abi/node_modules/#ethersproject/abi/lib/abi-coder.js:86:15)
at ABICoder.encodeParameters (-/node_modules/web3-eth-abi/lib/index.js:120:27)
at ABICoder.encodeParameter (-/node_modules/web3-eth-abi/lib/index.js:78:17) {
reason: 'value out-of-bounds',
code: 'INVALID_ARGUMENT',
argument: null,
value: '-1'
uint stands for "unsigned integer", so it doesn't accept -1 as a valid value.
Solidity converts uint(-1) to the maximal value of uint up to the version 0.7.6, because the value underflows.
pragma solidity ^0.7;
contract MyContract {
// returns 115792089237316195423570985008687907853269984665640564039457584007913129639935
function foo() external pure returns (uint256) {
return uint(-1);
}
}
Version 0.8.0 introduced automatic revert on integer underflow/overflow, and it doesn't even allow casting the -1 literal to uint, but you can test the revert this way:
pragma solidity ^0.8;
contract MyContract {
// reverts on underflow
function foo() external pure returns (uint256) {
uint256 number = 0;
number--;
return number;
}
}
Many JS libraries also don't allow passing -1 to the "unsigned integer" simply because it's an invalid value for the datatype. But since the -1 effectively represents the maximal value in older versions of Solidity, you can pass the uint maximal value.
For uint8, that's (2^8)-1 (or 255)
const BN = web3.utils.BN;
const number = (new BN(2)).pow(new BN(8)).sub(new BN(1));
console.log(number.toString());
For uint256, that's (2^256)-1 (or the large number starting 115...)
const BN = web3.utils.BN;
const number = (new BN(2)).pow(new BN(256)).sub(new BN(1));
console.log(number.toString());

Solidity and web3 sha3

I try to hash a tokenId with a seed in my smart contract. For simplicity and to avoid other errors I leave the seed out for now. I basically just want to hash a number on my contract and hash the same number on my javascript code and receive the same output.
Code looks something like this on Solidity:
function _tokenURI(uint256 tokenId) internal view returns (string memory) {
string memory currentBaseURI = _baseURI();
bytes32 hashedToken = keccak256(abi.encodePacked(tokenId));
return
bytes(currentBaseURI).length > 0
? string(abi.encodePacked(currentBaseURI, hashedToken, baseExtension))
: "";
}
which also leads to an error on client side invalid codepoint at offset. To tackle this I tried to cast bit32 to string using these functions
function _bytes32ToString(bytes32 _bytes32)
private
pure
returns (string memory)
{
uint8 i = 0;
bytes memory bytesArray = new bytes(64);
for (i = 0; i < bytesArray.length; i++) {
uint8 _f = uint8(_bytes32[i / 2] & 0x0f);
uint8 _l = uint8(_bytes32[i / 2] >> 4);
bytesArray[i] = _toByte(_f);
i = i + 1;
bytesArray[i] = _toByte(_l);
}
return string(bytesArray);
}
function _toByte(uint8 _uint8) private pure returns (bytes1) {
if (_uint8 < 10) {
return bytes1(_uint8 + 48);
} else {
return bytes1(_uint8 + 87);
}
}
though I'm not sure if this is equivalent. Code on the frontend looks like:
const hashed = web3.utils.soliditySha3(
{ type: "uint256", value: tokenId}
);
What do I need to change in order to receive the exact same output? And what does
invalid codepoint at offset
mean?
Maybe issue is that tokenId is not uint256 or Web3, Solidity version? I did few tests with Remix IDE and I recieved the same results.
Solidity code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Hash {
function getHashValue_1() public view returns(bytes32){
return keccak256(abi.encodePacked(uint256(234)));
}
// bytes32: 0x61c831beab28d67d1bb40b5ae1a11e2757fa842f031a2d0bc94a7867bc5d26c2
function getHashValue_3() public view returns(bytes32){
return keccak256(abi.encodePacked(uint256(10),string('StringSecretValue')));
}
// bytes32: 0x5938b4caf29ac4903ee34628c3dc1eb5c670a6bd392a006d0cb91f1fc5db3819
}
JS code:
(async () => {
try {
console.log('Web3 version is '+ Web3.version);
// Web3 version is 1.3.0
let theValueYouNeed = web3.utils.soliditySha3("234");
theValueYouNeed = web3.utils.soliditySha3({type: 'uint256', value: '234'});
theValueYouNeed = web3.utils.soliditySha3({t: 'uint256', v: '234'});
// above hashed value is 0x61c831beab28d67d1bb40b5ae1a11e2757fa842f031a2d0bc94a7867bc5d26c2
console.log('Hashed value 1 is '+theValueYouNeed);
theValueYouNeed = web3.utils.soliditySha3({t: 'uint256', v: '10'},{t: 'string', v: 'StringSecretValue'});
console.log('Hashed value 2 is '+theValueYouNeed);
// above hashed value is 0x5938b4caf29ac4903ee34628c3dc1eb5c670a6bd392a006d0cb91f1fc5db3819
} catch (e) {
console.log(e.message)
}
})()
I'm not sure but invalid codepoint at offset should mean that a designated value does not fall within the range or set of allowed values... So maybe there is something wrong with tokenId and you could do some tests with hardcoded values?
You get the invalid codepoint error because you mix string and byte data when you call abi.encodePacked(currentBaseURI, hashedToken, baseExtension)).
When Javascript gets the return value from the contract it expects a UTF8 string, but inside your hashedToken you have byte values that are not valid for a UTF8-encoded string.
This kind of error might be "intermittent". It might happen in just some cases. You're lucky to see it during development and not in production.
How to fix it?
You are on the right track converting the hash result to a string.
There is an alternative way to do it in this answer which uses less gas by using only bitwise operations.
To convert the hex value in Javascript you can use web3.utils.hexToNumberString().

What did I miss? No output is shown

//Q1.7
class Toing {
public static void main(String [] args){
}
public int distance(int sq1,int sq2){
int x1 = sq1%8;
int y1 = sq1/8;
int x2 = sq2%8;
int y2 = sq2/8;
double a = Math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
if(a % Math.sqrt(2) >= 1.41 && a % Math.sqrt(2) <= 1.42){
return (int) (Math.round(a/Math.sqrt(2)));
}
else if(sq2 == sq1){
return 0;
}
else {
return (int)a;
}
}
//Q1.8
public boolean sameColumn(int sq1,int sq2) {
return ((sq2 - sq1) % 8 == 0);
}
}
Hello, can someone help me if there's anything that I miss while doing these questions as when I run the command, it only shows "Run Toing". Is it suppose to show the answer or we just need to have the code only? As this question is about moving etc for example in
Q.1.7) the distance(0,63)=>6 . Should my output when I run the command show 6?
Q.1.8) sameColumn(10,12)=>true. Should my output when I run the command show true?
If yes, what do I miss writing it down on my commands as I cant think anymore as I wrote too many java thing today.. just want to check with you guys if anyone can help as I don't have someone that know java.. Thank you
To get out put you need to run the program. Right now main is empty and does nothing.
Here is an example of using Toing object:
public static void main(String [] args){
//create a Toing object
Toing t = new Toing();
//use it to calculate distance
int distance = t.distance(500,1200);
System.out.println("distance = "+ distance);
}
your main method is empty therefore the app is good design but doing nothing..
if you want to see some output in the console use System.out.println() method
in your case you need an instance of the class Toing
so do this:
public static void main(String [] args){
Toing myToingInstance = new Toing();
int distance = myToingInstance.distance(0,63);
System.out.println(" Tchebychev distance from 0 to 63 is: "+ distance);
}

Android Collections.min NoSuchElementException

Right now, I have a program that contains this piece of code:
if(Highest6.y == 0){
if(G.y == Collections.min(YUpper) && !notdone){ Highest6 = G; YUpper.remove(Integer.valueOf(G.y)); notdone = true;}
}
When I run it, I get this error:
The most interesting thing that I have identical snippets, which appear in different HighestX.y statements(I have six of them). And this error occurs only in the last one. Anybody knows why this keeps happening? Thanks in advance.
Here's code for my list:
List<Integer> YPoint = new java.util.ArrayList(Arrays.asList(A.y, B.y, C.y, D.y, E.y, F.y, G.y, K.y, Q.y, L.y, M.y, N.y));
List<Integer> YUpper = new java.util.ArrayList(Arrays.asList());
int Classified = 0;
int Highest = 0;
while(Classified != 6){
Highest = Collections.min(YPoint);
YPoint.remove(Integer.valueOf(Highest));
YUpper.add(Integer.valueOf(Highest));
Classified++;
}
I think the problem is that your collection is empty. From the documentation of Collections min returns:
NoSuchElementException - if the collection is empty
That is: your yUpper Arraylist is empty:
Collections.min(YUpper)
And it's empty because you never enter that while loop:
while(Classified != 6){
As classified is 0
Style note: use camelCase for variables & methods. That's the way Java code is meant to be written. Not MyVar but myVar. It's easier to read to Java people.

Categories