how to catch ethereum contract exception? - javascript

This is my simple contract
contract Test {
/* This creates an array with all balances */
mapping (address => uint256) public balanceOf;
/* Initializes contract with initial supply tokens to the creator of the contract */
function Test(
uint256 initialSupply
) {
balanceOf[msg.sender] = initialSupply; // Give the creator all initial tokens
}
/* Send coins */
function transfer(address _to, uint256 _value) {
if (balanceOf[msg.sender] < _value) throw; // Check if the sender has enough
if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
balanceOf[msg.sender] -= _value; // Subtract from the sender
balanceOf[_to] += _value; // Add the same to the recipient
}
function gettokenBalance(address to)constant returns (uint256){
return balanceOf[to];
}
}
When i am transferring tokens more than intial supply to another account the function transfer should throws exception.
How can i handle this exception and get to know transaction cannot complete.I am using web3j and calling function transfer like
Test test = Test.load(contractObj.getContractAddress(), web3j, credentials, gasprice,gaslimit);
TransactionReceipt balanceOf = test.transfer(new Address(address), transferBalance).get();

How can i handle this exception and get to know transaction cannot
complete
There is a single exception (a throw without arguments) in Solidity, which is "out of gas". So your "faulty" transaction is completed, however it ran out of gas. If you know the transaction hash, you can check gasLimit and gasUsed. If they are equal, your transaction has probably* ran out of gas. See more information here.
* given that you supply more than enough gas that a "correct" transaction requires.

I have never used web3js but you can try using try-catch:
try{
Test test = Test.load(contractObj.getContractAddress(), web3j, credentials, gasprice,gaslimit);
TransactionReceipt balanceOf = test.transfer(new Address(address), transferBalance).get();
} catch (Exception e){
// log you exception
}

Related

consensys solidity supply chain exercise

i'm currently passing 22 of 23 #openzeppelin/test-helpers when i run $ truffle test on my clone of the consensys supply-chain-exercise
why am i getting the following error and does it relate to the code below?
Wrong kind of exception received
+ expected - actual
-VM Exception while processing transaction: revert Not enough payment sent -- Reason given: Not enough payment sent.
+invalid opcode
SupplyChain.sol
modifier paidEnough(uint _price) {
require(msg.value >= _price, "Not enough payment sent"); // require(msg.value >= _price);
_;
}
function buyItem(uint sku) public payable forSale(sku) paidEnough(items[sku].price) checkValue(sku) { // 1. it should be payable in order to receive refunds
items[sku].seller.transfer(items[sku].price); // 2. this should transfer money to the seller
items[sku].buyer = msg.sender; // 3. set the buyer as the person who called this transaction
items[sku].state = State.Sold; // 4. set the state to Sold
// 5. this function should use 3 modifiers to check: if the item is for sale, if the buyer paid enough, and the value after the function is called to make sure the buyer is refunded any excess ether sent
emit LogSold(sku); // 6. call the event associated with this function
}
supply_chain.test.js
it("should error when not enough value is sent when purchasing an item", async () => {
await instance.addItem(name, price, { from: alice });
await expectRevert.assertion(instance.buyItem(0, { from: bob, value: 1 }));
});
thanks!

Calling a smart contract function using metamask with ether.js

I'm completely new to both blockchain and JavaScript.
I'm trying to create a simple web page where people could generate a "wedding" smart contract that basically store their 2 names. For this I have created a WeddingCerficate contract which store the names and have a getter function, and a WeddingCertificateFactory That enable me to generate a WeddingCertificate. You can find the code of the smart contracts in solidity below.
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
contract WeddingCertificate{
string private spouse1;
string private spouse2;
constructor(string memory _spouse1, string memory _spouse2) {
spouse1 = _spouse1;
spouse2 = _spouse2;
}
function getSpouses() public view returns (string memory,string memory) {
return (spouse1,spouse2);
}
}
contract WeddingCertificateFactory{
event Wedding(string _spouse1, string _spouse2, address indexed contract_adress );
function Unite(string memory _spouse1, string memory _spouse2)public returns (bool success) {
WeddingCertificate wedding = new WeddingCertificate(_spouse1, _spouse2);
emit Wedding(_spouse1,_spouse2 , address(wedding));
return true ;
}
}
I deployed the WeddingCertificateFactory on Goerli Tesnet. And now I'm trying to make a function in javascript (using ether.js) to enable a user to create his own weddingCertificate directly on a web interface.
For this I wrote the function below but for some reasons this only generates the new Wedding certificate once out 20. And even when it actually work, the two last print aren't visible in the console.
I do not get any error (at least that I can see in the console) when I test the function and nothing happen.
I'm not familiar with async in JavaScript, I also tried the .then( syntax but I didn't notice any difference.
async function CreateWedding(){
const spouse1 = document.getElementById("spouse1").value;
const spouse2 = document.getElementById("spouse2").value;
if (spouse1.length > 0 && spouse2.length >0) {
console.log(`spouse 1: ${spouse1} , spouse2 : ${spouse2} `);
const ethereum = window.ethereum ;
const accounts = await ethereum.request({
method: "eth_requestAccounts",
});
const provider = new ethers.providers.Web3Provider(ethereum, "any");
const walletAddress = accounts[0];
const signer = provider.getSigner(walletAddress);
let abi = [
" function Unite(string memory _spouse1, string memory _spouse2)"
];
const contractAddress = "0x2556Ff7f7F1c013bBB60bD120E1828032Cd84cc4"; //WeddingFactory Contract
const contract = new ethers.Contract(contractAddress, abi, signer);
console.log("sending the contract");
tx = await contract.Unite(spouse1,spouse2);
console.log(tx);
console.log("finished");
} else {
alert("Please enter 2 names");
}
}
Try creating your abi method in web3client.app.
It has code generater for ether.js which yoy can use directly in your app.
If there is an actual issue in your contract it would fail there itself.

Passing a Smart Contract Function Parameter Derived from a Struct to Its Interaction Script

I'm trying to interact with a contract I just deployed with a JavaScript file on HardHat. However, I'm getting an error; I know why it's being caused, but I don't know how to fix it. In my contract I have a struct defined as FlashParams, and I have a function that uses it as a parameter as seen here (it's only part of my code since I know the rest of it isn't causing any issues):
//fee1 is the fee of the pool from the initial borrow
//fee2 is the fee of the first pool to arb from
//fee3 is the fee of the second pool to arb from
struct FlashParams {
address token0;
address token1;
uint24 fee1;
uint256 amount0;
uint256 amount1;
uint24 fee2;
uint24 fee3;
}
// fee2 and fee3 are the two other fees associated with the two other pools of token0 and token1
struct FlashCallbackData {
uint256 amount0;
uint256 amount1;
address payer;
PoolAddress.PoolKey poolKey;
uint24 poolFee2;
uint24 poolFee3;
}
/// #param params The parameters necessary for flash and the callback, passed in as FlashParams
/// #notice Calls the pools flash function with data needed in `uniswapV3FlashCallback`
function initFlash(FlashParams memory params) external onlyOwner {
PoolAddress.PoolKey memory poolKey =
PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee1});
IUniswapV3Pool pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));
In my JS file I'm trying to pass the parameter from the contract as an argument in .initFlash(), but I don't know how to. Here's my JS file:
async function main() {
const address = '0x90A39BaC0D3A796b52f0394b9A97897d8F26eB1c8';
const PairFlash = await ethers.getContractFactory('PairFlash');
const pairflash = await PairFlash.attach(address);
const value = await pairflash.initFlash();
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
And here is the error:
Error: missing argument: passed to contract (count=0, expectedCount=1, code=MISSING_ARGUMENT, version=contracts/5.5.0)
reason: 'missing argument: passed to contract',
code: 'MISSING_ARGUMENT',
count: 0,
expectedCount: 1
Does anybody know how to fix this? Thank you!
I figured it out. The inputs for the JS file should be an a array format because this is the equivalent of a struct in solidity.

Create Solidity contract instance as a result of long running process

How can I write to the blockchain after an undetermined, time-consuming execution result?
Situation:
Web Client (NextJS): User requests a long running process that can take up to 1 hour to complete. As a result of this transaction, a new contract instance should be written to the blockchain. We can't expect the client to stick around waiting => use a NodeJS or cloud function to delegate the long running task. Metamask on the client will define the contract owner.
Planning to use NextJS to route to a Moralis Cloud Fx to kick off the long running task. The result of this long running task will be digital content to store to the blockchain.
Constraints/Problem:
Can’t have the user wait for the process to complete
Metamask runs on the client
Need Moralis Cloud Fx or NodeJS to have access to the owner to instantiate the contract at an undetermined future point in time.
From: sequencediagram.org
title Long Running Task to Blockchain
actor User
User->UI:User Request
UI->NodeServer: Delegate Slow Tasks
activate NodeServer
NodeServer->RestService: Start slow process
activate RestService
RestService-->NodeServer: Confirmation ID
NodeServer-->UI: Confirmation ID
UI->Blockchain: Create empty contract
RestService->NodeServer: Result = Data for blockchain
deactivate RestService
NodeServer->Blockchain: **Public?** Contract.setRestResult(Result)
deactivate NodeServer
Here is how I was planning to approach setting up the contract that would straddle the client and server.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
contract EncryptionNFT is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private tokenCounter;
uint256 public fee_wei;
bool public isLocked; // has a user paid to access the resource?
string private confirmationId; // long temporary password
string private sensitiveData; // data produced by long running process
address public encryptionService; // service responsible for producing the sensitive data
address public licensor; // licensed process
uint256 public tokenID; // distinct contract id
bool private isMutexed = false; // Reentrancy guard
bool private isSensitiveDataSet = false; // Asserts can only be set 1 time
event unlockPaid(address receiver, uint256 amount);
event withdrawlMade(address receiver, uint256 amount);
constructor(string memory name, uint256 _fee_gwei, string memory _confirmationId, address _encryption_service, address _licensor)
ERC721(name, "DataX")
{
fee_wei = _fee_gwei * 1000000000; // assert numbers are in WEI
isLocked = true; // lock contract by default since data not available => owner shouldn't have to pay unless successful
confirmationId = _confirmationId; // assign temporary password
encryptionService = _encryption_service; // assign addresses for payments
licensor = _licensor; // assign addresses for payments
tokenID = tokenCounter.current(); // Set/Mint with distinct token id
_safeMint(msg.sender, tokenID);
tokenCounter.increment();
}
function unlock() public payable {
require(isLocked == true, "Contract already unlocked.");
require(msg.value >= fee_wei, "Not enough WEI to unlock NFT.");
require(isMutexed == false, "Reentrant call detected!");
isMutexed = true;
// DO PAYMENTS
uint256 rcv_payment = msg.value;
uint256 licensor_cut = rcv_payment / 10;
uint256 encryptor_cut = rcv_payment - licensor_cut;
(bool is_encryptor_success, ) = payable(encryptionService).call{value: encryptor_cut}("");
require(is_encryptor_success, "Encryptor transfer failed.");
emit unlockPaid(encryptionService, encryptor_cut);
(bool is_licensor_success, ) = payable(licensor).call{value: licensor_cut}("");
require(is_licensor_success, "Licensor transfer failed.");
emit unlockPaid(licensor, licensor_cut);
isLocked = false;
isMutexed = false;
}
function withdraw() public payable {
require(msg.sender == ownerOf(tokenID), "Only owner may withdraw.");
require(isLocked == false, "Contract must be unlocked.");
require(isMutexed == false, "Reentrant call detected!");
isMutexed = true;
// DO PAYMENTS
uint256 rcv_payment = msg.value;
uint256 nft_service_cut = rcv_payment / 10;
uint256 licensor_cut = nft_service_cut / 10;
uint256 encryptor_cut = rcv_payment - licensor_cut;
uint256 nft_owner_cut = rcv_payment - nft_service_cut;
(bool is_encryptor_success, ) = payable(encryptionService).call{value: encryptor_cut}("");
require(is_encryptor_success, "Encryptor transfer failed.");
emit withdrawlMade(encryptionService, encryptor_cut);
(bool is_licensor_success, ) = payable(licensor).call{value: licensor_cut}("");
require(is_licensor_success, "Licensor transfer failed.");
emit withdrawlMade(licensor, licensor_cut);
(bool is_nft_owner_success, ) = payable(ownerOf(tokenID)).call{value: nft_owner_cut}("");
require(is_nft_owner_success, "NFT Owner transfer failed.");
emit withdrawlMade(ownerOf(tokenID), nft_owner_cut);
isMutexed = false;
}
function setTokenURI(string memory _tokenURI) public {
require(_isApprovedOrOwner(_msgSender(), tokenID), "ERC721: transfer caller is not owner nor approved.");
_setTokenURI(tokenID, _tokenURI);
}
// Here's how I was planning to allow a server-side process to set the data on REST service completion (slow task)
function setSensitiveData(string memory _confirmationId, string memory _sensitiveData) public {
require(keccak256(bytes(_confirmationId)) == keccak256(bytes(confirmationId)), "Confirmation ID does not match.");
require(isSensitiveDataSet == false, "Sensitive Data has already been set");
sensitiveData = _sensitiveData;
isSensitiveDataSet = true;
}
function getSensitiveData() public view returns (string memory){
require(isSensitiveDataSet == true, "Sensitive Data must be set first.");
require(msg.sender == encryptionService, "Only encryption service accessible.");
return sensitiveData;
}
}
Edit I just found Moralis has a session that appears to allow server side access as a corresponding user. Has anyone played with this before? Would it work for this use case?
Moralis Docs

Creating custom Ethereum token

I want to create my own Eth token, using Ethereum wallet and the code from this simple tutorial given in the ethereum.org website.
I don't have a programming background, knowing only basic info about JS and need a lot of help.
Custom ETH tokens are used, for example, as ICO to fund tech-based teams. If I understand correctly, when a certain address receives ETH (sent by a person to an ICO), the "contract" made by this ICO sends him back a portion of the custom tokens.
Is this present in the code below?
How can I edit the "ratio" between ETH and the custom token (example: you send 1 ETH and receive 588 c.tokens - ratio 1:588)?
pragma solidity ^0.4.8;
contract tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData); }
contract MyToken {
/* Public variables of the token */
string public standard = 'Token 0.1';
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
/* This creates an array with all balances */
mapping (address => uint256) public balanceOf;
mapping (address => mapping (address => uint256)) public allowance;
/* This generates a public event on the blockchain that will notify clients */
event Transfer(address indexed from, address indexed to, uint256 value);
/* This notifies clients about the amount burnt */
event Burn(address indexed from, uint256 value);
/* Initializes contract with initial supply tokens to the creator of the contract */
function MyToken(
uint256 initialSupply,
string tokenName,
uint8 decimalUnits,
string tokenSymbol
) {
balanceOf[msg.sender] = initialSupply; // Give the creator all initial tokens
totalSupply = initialSupply; // Update total supply
name = tokenName; // Set the name for display purposes
symbol = tokenSymbol; // Set the symbol for display purposes
decimals = decimalUnits; // Amount of decimals for display purposes
}
/* Send coins */
function transfer(address _to, uint256 _value) {
if (_to == 0x0) throw; // Prevent transfer to 0x0 address. Use burn() instead
if (balanceOf[msg.sender] < _value) throw; // Check if the sender has enough
if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
balanceOf[msg.sender] -= _value; // Subtract from the sender
balanceOf[_to] += _value; // Add the same to the recipient
Transfer(msg.sender, _to, _value); // Notify anyone listening that this transfer took place
}
/* Allow another contract to spend some tokens in your behalf */
function approve(address _spender, uint256 _value)
returns (bool success) {
allowance[msg.sender][_spender] = _value;
return true;
}
/* Approve and then communicate the approved contract in a single tx */
function approveAndCall(address _spender, uint256 _value, bytes _extraData)
returns (bool success) {
tokenRecipient spender = tokenRecipient(_spender);
if (approve(_spender, _value)) {
spender.receiveApproval(msg.sender, _value, this, _extraData);
return true;
}
}
/* A contract attempts to get the coins */
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
if (_to == 0x0) throw; // Prevent transfer to 0x0 address. Use burn() instead
if (balanceOf[_from] < _value) throw; // Check if the sender has enough
if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
if (_value > allowance[_from][msg.sender]) throw; // Check allowance
balanceOf[_from] -= _value; // Subtract from the sender
balanceOf[_to] += _value; // Add the same to the recipient
allowance[_from][msg.sender] -= _value;
Transfer(_from, _to, _value);
return true;
}
function burn(uint256 _value) returns (bool success) {
if (balanceOf[msg.sender] < _value) throw; // Check if the sender has enough
balanceOf[msg.sender] -= _value; // Subtract from the sender
totalSupply -= _value; // Updates totalSupply
Burn(msg.sender, _value);
return true;
}
function burnFrom(address _from, uint256 _value) returns (bool success) {
if (balanceOf[_from] < _value) throw; // Check if the sender has enough
if (_value > allowance[_from][msg.sender]) throw; // Check allowance
balanceOf[_from] -= _value; // Subtract from the sender
totalSupply -= _value; // Updates totalSupply
Burn(_from, _value);
return true;
}
}
1) get amount of custom token (msg.value/ratioAmount)
2) transfer that amount to the requester
you have to use a payable fallback function in which you should call a function which will be dealing with above two mentioned activities.
Send() will invoke payable fallback function which in turn call your custom function which will be doing the actual work.
Check fallback function in solidity documentation.
payable is necessary for send() after DAO incident.

Categories

Resources