CONTRACT_REVERT_EXECUTED Hedera Smart Contract - solidity

CONTRACT_REVERT_EXECUTED
Not sure what I'm doing wrong but I'm trying to call a function and it takes in one parameter and I made sure it was correct but it still reverts. This is hedera-hashgraph using HederaTokenService.
Smart Contract:
pragma solidity ^0.8.11;
import "./hip-206/HederaTokenService.sol";
import "./hip-206/HederaResponseCodes.sol";
contract Minting is HederaTokenService {
address tokenAddress;
bytes metadata;
string baseURI = "abc";
uint64 mintPrice;
function mintNonFungibleToken(uint64 _amount) external payable {
bytes[] memory nftMetadatas = generateBytesArrayForHTS(
baseURI,
_amount
);
(
int256 response,
uint64 newTotalSupply,
) = HederaTokenService.mintToken(tokenAddress, _amount, metadata);
if (response != HederaResponseCodes.SUCCESS) {
revert("Mint Failed");
}
}
// #dev Helper function which generates array of addresses required for HTSPrecompiled
function generateAddressArrayForHTS(address _address, uint256 _items)
internal
pure
returns (address[] memory _addresses)
{
_addresses = new address[](_items);
for (uint256 i = 0; i < _items; i++) {
_addresses[i] = _address;
}
}
// #dev Helper function which generates array required for metadata by HTSPrecompiled
function generateBytesArrayForHTS(bytes memory _bytes, uint256 _items)
internal
pure
returns (bytes[] memory _bytesArray)
{
_bytesArray = new bytes[](_items);
for (uint256 i = 0; i < _items; i++) {
_bytesArray[i] = _bytes;
}
}
Calling the transaction in js:
const contractMint = await new ContractExecuteTransaction()
.setContractId(contractId)
.setGas(3000000)
.setFunction(
"mintFungibleToken",
new ContractFunctionParameters().addUint64(1)
)
.setMaxTransactionFee(new Hbar(2));

Also note that a REVERT does usually contain useful information, you can navigate to hashscan.io to look up the response from your smart contract, for example
https://hashscan.io/testnet/transaction/1675427464.278782297?tid=0.0.1189-1675427451-309271560
shows a contract that reverted, the error message is 0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001b52656d697420746f6b656e20616c726561647920637265617465640000000000
with the error message starting with 0x08c379a, we know it's a string, so we can decode it
Hacky way:
Navigate to: https://www.rapidtables.com/convert/number/hex-to-ascii.html
Paste the above (remove the 0x)
Choose ASCII for character encoding
Press convert
Output: Ãy  Remit token already created
In Javascript
const {ethers} = require("ethers");
async function main() {
const error = "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001b52656d697420746f6b656e20616c726561647920637265617465640000000000";
const reason = ethers.utils.defaultAbiCoder.decode(
['string'],
ethers.utils.hexDataSlice(error, 4)
)
console.log(reason);
};
void main();

It looks like you're trying to call mintFungibleToken from JS, but the smart contract doesn't have a mintFungibleToken function; the smart contract function name is mintNonFungibleToken.

Related

How do I call diamondCut (EIP-2535) from another contract?

I'm trying to call execute the diamondCut function using another contract, but it keeps getting reverted, even though all the facet addresses and respective function selectors exist and are included in the call. I'm trying to do the following:
Remove 3 functions, each function is in a separate facet, using the cutSomeDiamonds function in this contract
The interfaces used are in https://github.com/mudgen/diamond-1-hardhat/tree/main/contracts/interfaces
contract ExecuteDiamondCuts {
address CONTRACT_ADDRESS = 0xblahblah; // dummy address
string[] functionsToRemove;
constructor() {
functionsToRemove.push("exampleFunctionA(address)");
functionsToRemove.push("exampleFunctionB(uint)");
functionsToRemove.push("exampleFunctionC()");
}
function cutSomeDiamonds() external {
IDiamondLoupe _loupe = IDiamondLoupe(CONTRACT_ADDRESS);
IDiamondCut.FacetCut[] memory _facetCuts = new IDiamondCut.FacetCut[](functionsToRemove.length);
for (uint i=0; i<functionsToRemove.length; i++) {
address facetWithFn = _loupe.facetAddress(bytes4(keccak256(bytes((functionsToRemove[i])))));
bytes4[] memory _fnSelectors = new bytes4[](1);
_fnSelectors[0] = bytes4(keccak256(bytes((functionsToRemove[i]))));
IDiamondCut.FacetCut memory _facetCut = IDiamondCut.FacetCut({
facetAddress: facetWithFn, // facet address
action: IDiamondCut.FacetCutAction.Remove, // action
functionSelectors: _fnSelectors // array of fn selectors
});
_facetCuts[i] = _facetCut;
}
(bool success,) = CONTRACT_ADDRESS.delegatecall(
abi.encodeWithSignature(
"diamondCut(FacetCut[],address,bytes)",
_facetCuts,
address(0),
"0x"
)
);
require(success);
}
}
Everything seems to work until require(success); which got reverted.

contracts/3_Ballot.sol:33:37: TypeError: Named argument does not match function declaration

from solidity:
contracts/3_Ballot.sol:33:37: TypeError: Named argument does not match function declaration.
Request memory newRequest = Request({
^ (Relevant source part starts here and spans across multiple lines).
I get this error every time. What should i do for the solve it?
pragma solidity ^0.4.17;
contract Campaign {
struct Request {
string description;
uint value;
address recipient;
bool complete;
}
Request[] public requests;
address public manager;
uint public minimumContirbution;
address[] public approvers;
modifier restricted() {
require (msg.sender == manager);
_;
}
function Campaign (uint minimum) public {
manager = msg.sender;
minimumContirbution = minimum;
}
function contribute () public payable {
require(msg.value > minimumContirbution);
approvers.push(msg.sender);
}
function createRequest(string description, uint value, address recipient) restricted public {
Request memory newRequest = Request({
description: description,
value: value,
restricted: restricted,
complete: false
});
requests.push(newRequest);
}
}
You can define the Request struct in this way and push it into requests array:
function createRequest(string description, uint value, address recipient) restricted public {
Request memory newRequest = Request(description, value, recipient, false);
requests.push(newRequest);
}
In this way, you can add the struct into your array and can retrieve with all parameters setted previously.
Because you're are using wrong argument(restricted) inside you Request type
try this:
Request memory newRequest = Request({
descritption: descritpion,
value: value,
recipient: recipient,
complete: false
});

_signTypedData method on ethers does not match with ERC712 solidity code

I've faced an ethers signature unmatched problem.
Everything is normal.
Already compared domainData, types, message variable in the js code with contract.
Below is the JS Code to generate signature and call contract.
const contractAddress = await contract.address;
domainData.chainId = 31337;
domainData.verifyingContract = contractAddress;
const signature = await signer._signTypedData(domainData, types, message);
const { r, s, v } = ethers.utils.splitSignature(signature);
const result = await contract.recoverAddressFromTypedData(
message,
v,
r,
s
);
expect(result).to.equal(signer.address);
Below is the solidity code which use "#openzeppelin/contracts/utils/cryptography/draft-EIP712.sol"
function recoverAddressFromTypedData(
Bid memory bid,
uint8 v,
bytes32 r,
bytes32 s
) public view returns (address) {
bytes32 digest = _hashTypedDataV4(hashBid(bid));
address signer = ecrecover(digest, v, r, s);
return signer;
}
But I got following error on the last line of JS code.
AssertionError: expected '0x7Da34C07B95dB4A1c85fe4C5d313F4860E85e340' to equal '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
+ expected - actual
-0x7Da34C07B95dB4A1c85fe4C5d313F4860E85e340
+0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
Is there anything wrong with my code?
I don't know if I have the same reason as you, in my case I had a struct member containing a string type which needed to be converted to bytes32.
contract MyContract is Ownable, AccessControl, EIP712 {
struct Action {
address initiator;
string name;
}
bytes32 public constant ACTION_TYPE_HASH = keccak256("Action(address initiator,string name)");
function _hashStruct(Action memory action) private pure returns (bytes32) {
// If your struct member has string type,
// you need to use keccak256(abi.encodePacked(string))
// convert it to bytes32
return keccak256(abi.encode(ACTION_TYPE_HASH, action.initiator, keccak256(abi.encodePacked(action.name))));
}
function _hashTypedDataV4(Action memory action) private view returns (bytes32) {
bytes32 structHash = _hashStruct(action);
return EIP712._hashTypedDataV4(structHash);
}
// more...
}

How to make an API call in solidity?

I have a smart contract that I’m trying to make, it pays out the winners of my League of Legends tournament. However I’m running into an issue. I need to make an API call to get the winner of the match, I have a simple URL that I’ve make.
"example-winner.com/winner"
And it returns simple JSON with the address of the winner:
{"winner":"0xa7D0......."}
However, I’m not sure how to make the API call to the outside function. I know I need to use some sort of oracle technology.
Any thoughts? Below is my code:
pragma solidity ^0.4.24;
contract LeagueWinners{
address public manager;
address[] public players;
uint256 MINIMUM = 1000000000000000;
constructor() public{
manager = msg.sender;
}
function enter() public payable{
assert(msg.value > MINIMUM);
players.push(msg.sender);
}
function getWinner() public{
assert(msg.sender == manager);
// TODO
// Get the winner from the API call
result = 0; // the result of the API call
players[result].transfer(address(this).balance);
// returns an adress object
// all units of transfer are in wei
players = new address[](0);
// this empties the dynamic array
}
}
You can use Chainlink as your Oracle.
As many have mentioned, you will need an oracle to get your API call. Something that is important to note, your contract is actually asking an oracle to make your API call for you, and not making the API call itself. This is because the blockchain is deterministic. For more information see this thread.
To answer your question, you can use the decentralized oracle service Chainlink.
You'd add a function:
function getWinner()
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(JOB, address(this), this.fulfill.selector);
req.add("get", "example-winner.com/winner");
req.add("path", "winner");
sendChainlinkRequestTo(ORACLE, req, ORACLE_PAYMENT);
}
For the purpose of the following exmaple, we are going to pretend you want to return a uint256 instead of an address. You can return a bytes32 and then convert it to an address, but for simplicity let's say the API returns the index of the winner. You'll have to find a node and jobId that can make a http.get request and return a uint256 object. You can find nodes and jobs from market.link. Each testnet (Ropsten, Mainnet, Kovan, etc) has different node addresses, so make sure you pick the right ones.
For this demo, we are going to use LinkPool's ropsten node
address ORACLE=0x83F00b902cbf06E316C95F51cbEeD9D2572a349a;
bytes32 JOB= "c179a8180e034cf5a341488406c32827";
Ideally, you'd choose a number of nodes to run your job, to make it trustless and decentralized. You can read here for more information on precoordinators and aggregating data. disclosure I am the author of that blog
Your full contract would look like:
pragma solidity ^0.6.0;
import "github.com/smartcontractkit/chainlink/evm-contracts/src/v0.6/ChainlinkClient.sol";
contract GetData is ChainlinkClient {
uint256 indexOfWinner;
address public manager;
address payable[] public players;
uint256 MINIMUM = 1000000000000000;
// The address of an oracle
address ORACLE=0x83F00b902cbf06E316C95F51cbEeD9D2572a349a;
//bytes32 JOB= "93fedd3377a54d8dac6b4ceadd78ac34";
bytes32 JOB= "c179a8180e034cf5a341488406c32827";
uint256 ORACLE_PAYMENT = 1 * LINK;
constructor() public {
setPublicChainlinkToken();
manager = msg.sender;
}
function getWinnerAddress()
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(JOB, address(this), this.fulfill.selector);
req.add("get", "example-winner.com/winner");
req.add("path", "winner");
sendChainlinkRequestTo(ORACLE, req, ORACLE_PAYMENT);
}
// When the URL finishes, the response is routed to this function
function fulfill(bytes32 _requestId, uint256 _index)
public
recordChainlinkFulfillment(_requestId)
{
indexOfWinner = _index;
assert(msg.sender == manager);
players[indexOfWinner].transfer(address(this).balance);
players = new address payable[](0);
}
function enter() public payable{
assert(msg.value > MINIMUM);
players.push(msg.sender);
}
modifier onlyOwner() {
require(msg.sender == manager);
_;
}
// Allows the owner to withdraw their LINK on this contract
function withdrawLink() external onlyOwner() {
LinkTokenInterface _link = LinkTokenInterface(chainlinkTokenAddress());
require(_link.transfer(msg.sender, _link.balanceOf(address(this))), "Unable to transfer");
}
}
This would do about everything you need.
If you can't adjust the API to return a uint, you can return a bytes32 and then convert it to an address or a string.
function bytes32ToStr(bytes32 _bytes32) public pure returns (string memory) {
bytes memory bytesArray = new bytes(32);
for (uint256 i; i < 32; i++) {
bytesArray[i] = _bytes32[i];
}
return string(bytesArray);
}
You cannot. The vm does not have any I/O outside of the blockchain itself. Instead you will need to tell your smart contract who the winner is and then the smart contract can just read the value of that variable.
This design pattern is also known as the "oracle". Google "Ethereum oracle" for more info.
Basically your web server can call your smart contract. Your smart contract cannot call your web server. If you need your smart contract to access a 3rd party service then your web server will need to make the request then forward the result to solidity by calling a function in your smart contract.
You didn't properly explain what you are trying to do. Are you having trouble with the solidity code? or rather with your server? Here is an edited version. See if it helps.
pragma solidity ^0.4.24;
contract LeagueWinners{
address public manager;
//address[] public players;
uint256 MINIMUM = 1000000000000000;
constructor() public{
manager = msg.sender;
}
struct Player {
address playerAddress;
uint score;
}
Player[] public players;
// i prefer passing arguments this way
function enter(uint value) public payable{
assert(msg.value > MINIMUM);
players.push(Player(msg.sender, value));
}
//call this to get the address of winner
function winningPlayer() public view
returns (address winner)
{
uint winningScore = 0;
for (uint p = 0; p < players.length; p++) {
if (players[p].score > winningScore) {
winningScore = players[p].score;
winner = players[p].playerAddress;
}
}
}
// call this to transfer fund
function getWinner() public{
require(msg.sender == manager, "Only a manager is allowed to perform this operation");
// TODO
address winner = winningPlayer();
// Get the winner from the API call
//uint result = 0; // the result of the API call
winner.transfer(address(this).balance);
// returns an adress object
// all units of transfer are in wei
delete players;
// this empties the dynamic array
}
}
At least that is what I understand by your question.

Transfer ownership web3

I am creating a dapp to transfer ownership of the contract from one address to another using testrpc. However,I keep encountering this problem. I have tried using sentransaction method to do perform this ownership change.Perhaps I'm calling the exchange in a wrong manner.
Solidity version 0.4.4
web3 "version": "0.20.2"
web3.js:3127 Uncaught Error: VM Exception while processing transaction: invalid opcode
at Object.InvalidResponse (web3.js:3127)
at RequestManager.send (web3.js:6332)
at Eth.send [as sendTransaction] (web3.js:5066)
at SolidityFunction.sendTransaction (web3.js:4122)
at SolidityFunction.execute (web3.js:4208)
at transferOwnership (luxcure_manu.html:309)
at HTMLButtonElement.onclick (luxcure_manu.html:378
Full solidity contract as of yet.
pragma solidity ^0.4.4;
// TODO: Hash of the cert through IPFS Hash
// Transfer ownership of smart contract
contract LuxSecure {
address public contract_owner; //Manufacturer/owner
//string public current_owner; //Current Owner of good
bytes32 public model; //Model
mapping(uint => address) public owners; //list of owners
uint256 public owners_count;
bytes32 public status; // (Public(Owned by no one), Private(Bought by another entity),stolen(Stolen from public or private))
bytes32 public date_manufactured; //Time
// Set manufacturer of the Good RUN ONCE ONLY
function manufacturer() public{
if(owners_count == 0){
contract_owner = msg.sender;
}
}
//Modifier that only allows owner of the bag to Smart Contract AKA Good to use the function
modifier onlyOwner(){
require(msg.sender == contract_owner);
_;
}
// Add a new product to the blockchain with a new serial
function addNewGoods(bytes32 _model,bytes32 _status, bytes32 _date_manufactured) public returns(bool made) {//Declare Goods struct
setOwner(msg.sender);
model = _model;
status = _status;
date_manufactured = _date_manufactured;
return true;
}
//This function transfer ownership of contract from one entity to another
function transferOwnership(address _newOwner) public onlyOwner(){
require(_newOwner != address(0));
contract_owner = _newOwner;
}
//Set the KEY to uint256 and VALUE owner Ethereum Address
function setOwner(address owner)public{
owners_count += 1 ;
owners[owners_count] = owner;
}
//Get the previous owner in the mappings
function previousOwner()constant public returns(address){
if(owners_count != 0){
uint256 previous_owner = owners_count - 1;
return owners[previous_owner];
}
}
// Getter Methods
function getManufacturer() constant public returns(address){
return contract_owner;
}
function getCurrentOwner() constant public returns(address){
return owners[owners_count] ;
}
function getOwnerCount() constant public returns(uint256){
return owners_count;
}
function getModel() constant public returns(bytes32){
return model;
}
function getStatus() constant public returns(bytes32){
return status;
}
function getDateManufactured() constant public returns(bytes32){
return date_manufactured;
}
}// end of LuxSecure
Javascript to perform the transfer of ownership
function transferOwnership(){
var account_to_transfer = document.getElementById("ethereumaddress").value;
contract.transferOwnership(account_to_transfer,{
from:web3.eth.accounts[0],
gas:4000000
});
}
I don't see any particular mistake in your code. Maybe a bad formatting on the front-side, but can't guess for sure as we have partial front here.
I don't know if it will be some help but sometimes, using truffle, it happened to me to have some functions that returned bad opcode from testrpc/ganache-cli while no apparent error was in the code.
Deleting the ABI, recompiling the smart-contracts to get a brand new ABI and then redeploying the contracts solved the problem.