How to call run-local (without sending a message) function of another contract from debot? For example, for getting a public variable.
This was useful for me.
In debot:
Create interface for function of another contract with function (if public variable too).
interface IOther {
function funcName()
external returns(uint);
}
Build the message and send it.
function runLocal() public{
optional(uint256) pubkey = 0;
address remoteContract = address.makeAddrStd(0, 0xceaa3bc6b00cf2b1e750dae2dd94d246a126a989009a3fb3bb73bea1a48b3b);
TvmCell message = tvm.buildExtMsg({
abiVer: 2,
callbackId: tvm.functionId(onSuccessFuncName),
onErrorId: tvm.functionId(onErrorFuncName),
time: uint64(now),
dest: remoteContract,
call: {
IOther.funcName
}
});
tvm.sendrawmsg(message, 1);
}
function onSuccessFuncName(uint response) public{
/* working with response from remote contract */
}
function onErrorFuncName() public{
/* catch error */
}
Related
I'm new to Solidity but I can't find much information about my problem.
For example, I want to make different contracts for different functionalities (I see them as classes)
For example
Main contract
// SPDX-License-Identifier: None
pragma solidity >=0.8.6;
import "./AuthContract.sol";
contract Contract {
string public message;
constructor() {
message = "test";
}
function getMessage() public view returns(string memory) {
return message;
}
}
and second contract
contract Auth {
struct UserDetail {
address addr;
string name;
string password;
string CNIC;
bool isUserLoggedIn;
}
mapping(address => UserDetail) user;
// user registration function
function register(
address _address,
string memory _name,
string memory _password,
string memory _cnic
) public returns (bool) {
require(user[_address].addr != msg.sender);
user[_address].addr = _address;
user[_address].name = _name;
user[_address].password = _password;
user[_address].CNIC = _cnic;
user[_address].isUserLoggedIn = false;
return true;
}
// user login function
function login(address _address, string memory _password)
public
returns (bool)
{
if (
keccak256(abi.encodePacked(user[_address].password)) ==
keccak256(abi.encodePacked(_password))
) {
user[_address].isUserLoggedIn = true;
return user[_address].isUserLoggedIn;
} else {
return false;
}
}
// check the user logged In or not
function checkIsUserLogged(address _address) public view returns (bool) {
return (user[_address].isUserLoggedIn);
}
// logout the user
function logout(address _address) public {
user[_address].isUserLoggedIn = false;
}
}
How could I use the functionalities from that contract in the main contract?
Is such a thing possible in the blockchain?
I am quite new here also but i can solve your problem, if not solve i can lead you to a good path .
so firstly you said you want to create multiple contract for different functionalities, this is good but keep in my you are going to exhaust a lot of gas.
so the answer to your problem is easy you can just read it and implement it.
if you want to use a contract in the Another contract (main in your case) you can do it in two ways(according to my knowledge there might be other).
using new keyword
using address of your previously deployed contract
we will be using the First case as i suppose you havenot deployed the second contract yet
In Order to do it you can use
Auth myObj=new Auth();
This will create a new instance of the contract Auth in your main contract and now you can use the Auth contract's function in your Main contract.you can create a function copy the above line and you can use the Functions using dot operator.
myObj.register(_address,_name,moreandmore);
I believe this will solve your problem if not you can ask it.
Thank You!
I am trying the below code, elementary reentrancy example.
The current code works but transfer or send doesn't work. It reverts. What are the reasons?
Note: I chose setCaller to reenter to test the fact that updating the dirty state variable (already modified var in the same tx) takes less gas.
// SPDX-License-Identifier: Unlicensed
pragma solidity 0.8.7;
contract TestFund {
// success, if caller is itself.
address public caller;
constructor() payable {}
function getBalance() public view returns (uint) {
return address(this).balance;
}
function emptyFn(address dummy) public {}
function setCaller(address _caller) public {
caller = _caller;
}
function withdraw() external {
caller = msg.sender;
// require(payable(msg.sender).send(1 wei));
// payable(msg.sender).transfer(1 wei);
(bool success, bytes memory data) = payable(msg.sender).call{gas: 2300, value:1 wei}("");
require(success);
}
}
contract Attack {
function getBalance() public view returns (uint) {
return address(this).balance;
}
function attack(address target) external {
TestFund(target).withdraw();
}
receive() external payable {
if (getBalance() == 1 wei) {
TestFund(msg.sender).setCaller(msg.sender);
}
}
}
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.
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.
I'm new to write a smart contract with Ethereum.
According to an official document, compiling a smart contract needs to remove all the line-breaks in the contract's source-code :
var greeterSource = 'contract mortal { address owner; function mortal() { owner = msg.sender; } function kill() { if (msg.sender == owner) suicide(owner); } } contract greeter is mortal { string greeting; function greeter(string _greeting) public { greeting = _greeting; } function greet() constant returns (string) { return greeting; } }'
var greeterCompiled = web3.eth.compile.solidity(greeterSource)
https://ethereum.gitbooks.io/frontier-guide/content/contract_greeter.html
As I think the removing process is not smart, I want to compile the code itself like:
var greeterCompiled = web3.eth.compile.solidity_infile( "greeter.txt" )
# The function "solidity_infile" does not exists actually,
# but represents what I want to do.
greeter.txt
contract
mortal {
/* Define variable owner of the type address*/
address owner;
/* this function is executed at initialization and sets the owner of the contract */
function mortal() { owner = msg.sender; }
/* Function to recover the funds on the contract */
function kill() { if (msg.sender == owner) suicide(owner); }
}
contract greeter is mortal {
/* define variable greeting of the type string */
string greeting;
/* this runs when the contract is executed */
function greeter(string _greeting) public {
greeting = _greeting;
}
/* main function */
function greet() constant returns (string) {
return greeting;
}
}
Does anyone how to do that?
The compiler I'm using is Solidity.
How about loading the contract from a file into var someContractText and then do the following
someContractText = someContractText.replace(/(\r\n|\n|\r)/gm,"");