Sign and broadcast smart contract transaction in TRON network - blockchain

Using a node.js client, I'm trying to invoke a smart contract function by:
Creating a transaction
Signing it
Broadcast the signed transaction
I deployed a simple smart contract:
pragma solidity ^0.4.25;
contract Test {
event MyEvent(address sender, string message, uint sessionId, uint value);
event TestEvent(address sender);
constructor() public {
}
function testFunction(string message, uint sessionId)
public
payable {
emit MyEvent(msg.sender, message, sessionId, msg.value);
}
function test2()
public {
emit TestEvent(msg.sender);
}
}
I'm having success invoking test2 (when sending an empty parameters array) but failing to invoke testFunction which takes parameters.
I've tried using tronweb triggerSmartContract call:
async function triggerSmartContract() {
try {
const options = {
feeLimit: 1000000000,
callValue: 50
};
const parameters = [{type: 'string', value: 'test-round-id-1'}, {type: 'uint', value: 12345}];
const issuerAddress = tronWeb.defaultAddress.base58;
const functionSelector = 'testFunction(string, uint)';
let transactionObject = await tronWeb.transactionBuilder.triggerSmartContract (
contract_address,
functionSelector,
options,
parameters,
tronWeb.address.toHex(issuerAddress)
);
if (!transactionObject.result || !transactionObject.result.result)
return console.error('Unknown error: ' + txJson, null, 2);
// Signing the transaction
const signedTransaction = await tronWeb.trx.sign(transactionObject.transaction);
if (!signedTransaction.signature) {
return console.error('Transaction was not signed properly');
}
// Broadcasting the transaction
const broadcast = await tronWeb.trx.sendRawTransaction(signedTransaction);
console.log(`broadcast: ${broadcast}`);
} catch (e) {
return console.error(e);
}
}
The code runs and creates a transaction on the blockchain but with result of FAIL-REVERT OPCODE EXECUTED.
The wallet of the address and key that are defined in tronweb object has enough funds in it (it's not out of gas/not enough funds matter).
Also the function in the smart contract is defined as payable.
Since I can invoke successfully any function with no parameters I tend to think the problem relates to the way I construct the parameters array. I built the parameters array this way (pairs of type and value) after going over the source code of the transactionBuilder (line 833).
Any suggestions?

Had exactly the same issue. Solution:
Remove spaces in const functionSelector = 'testFunction(string,uint)'; as malysh advised
Change uint to uint256

try writing function parameters without spaces.const functionSelector = 'testFunction(string,uint)'; I read in the documentation that you have to write without spaces, it worked for me on python.

Related

Parser error when trying to run a smart contract

I'm very new to smart contract development , and I had just deployed my first contract on ganache.
Here's the code of SimpleLearn.sol
contract SimpleLearn
{
address public payer;
address public thirdParty;
address public receiver;
uint public amt;
uint senderBal;
uint remamount;
constructor (address _payer, uint amount, address _receiver) // constructor is invoked only once for entire
// contract. mostly thats why invoked by thirdParty
{
payer = _payer;
receiver = _receiver;
amt = amount;
thirdParty = msg.sender;
remamount = amount;
}
mapping (address=>uint) public balances;
function deposit(uint transferm) public returns (uint)
{
require (msg.sender == payer, "Sender must be payer");
require (transferm< remamount, "Amount to transfer should be lesser than remaining amount");
remamount = remamount - transferm;
balances[thirdParty] += transferm;
return remamount;
//return msg.sender.balance;
}
}
This is the code for 2_deploy_contract.js
module.exports = function(deployer) {
deployer.deploy(SimpleLearn,'0x21DB98979bc3a42D58648cC22c47C11610f2E094',50,'0x62F49aE035648325320454cC8B3934F3c8c36A77');
};
when I am trying to create an instance of the contract using deployed() method as follows:
let newinst = await SimpleLearn.deployed()
it is returning me a parse error as follows
Note : I have already deployed my smart contract to a private blockchain using ganache
I am not able to understand what I am missing ? Kindly help me out ! Thank you !
I think that is because you are not in truffle development environment. first make sure ganache is running. in your truffle project directory
truffle console

What are the functions setPublicChainlinkToken & setChainlinkToken in Chainlink API call?

I was following the tutorial of Chainlink docs at https://docs.chain.link/docs/advanced-tutorial/ to make an API call from my smart contract. However, I am still not able to understand the function setPublicChainlinkToken() that is being called in the constructor of APIConsumer.
I am trying to fetch the temperature of a city through the API call. But my contract gives an error in compilation saying:
APIConsumer hit a require or revert statement somewhere in its constructor
The above error is very generic and I am unable to understand what is the issue. Below is my contract code and the script which I am using to deploy it.
What params do I need to pass in the deploy script?
APIConsumer contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "#chainlink/contracts/src/v0.6/ChainlinkClient.sol";
/**
* THIS IS AN EXAMPLE CONTRACT WHICH USES HARDCODED VALUES FOR CLARITY.
* PLEASE DO NOT USE THIS CODE IN PRODUCTION.
*/
contract APIConsumer is ChainlinkClient {
using Chainlink for Chainlink.Request;
uint256 public temperature;
address private oracle;
bytes32 private jobId;
uint256 private fee;
constructor () public {
setPublicChainlinkToken(); // Do I need to pass any params for this?
// if (_link == address(0)) {
// setPublicChainlinkToken();
// } else {
// setChainlinkToken(_link);
// }
// setPublicChainlinkToken();
oracle = <oracle id>; // Removed oracle id and jobid values for post
jobId = <job id>;
fee = 0.1 * 10 ** 18; // 0.1 LINK (Varies by network and job)
}
/**
* Create a Chainlink request to retrieve API response, find the target
* data, then multiply by 1000000000000000000 (to remove decimal places from data).
*/
function requestVolumeData() public returns (bytes32 requestId)
{
Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);
// Set the URL to perform the GET request on
// "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD"
request.add("get", "http://api.weatherstack.com/current?access_key=7940b0c1136901badcb304724132b234&query=Mumbai");
// Set the path to find the desired data in the API response, where the response format is:
// {"RAW":
// {"ETH":
// {"USD":
// {
// "VOLUME24HOUR": xxx.xxx,
// }
// }
// }
// }
request.add("path", "current.temperature");
// Multiply the result by 1000000000000000000 to remove decimals
// int timesAmount = 10**18;
// request.addInt("times", timesAmount);
// Sends the request
return sendChainlinkRequestTo(oracle, request, fee);
}
/**
* Receive the response in the form of uint256
*/
function fulfill(bytes32 _requestId, uint256 _temperature) public recordChainlinkFulfillment(_requestId)
{
temperature = _temperature;
}
// function withdrawLink() external {} - Implement a withdraw function to avoid locking your LINK in the contract
}
Javascript Script To Deploy:
const APIConsumer = artifacts.require("APIConsumer");
module.exports = async (deployer, network, [defaultAccount]) => {
try {
await deployer.deploy(APIConsumer);
} catch (err) {
console.error(err);
}
};
setChainlinkToken is a function that tells the oracle contract what it should use to accept LINK payments. It points to an ERC677 token for the contracts to use.
You have to know what the LINK token address is to use this function.
The setPublicChainlinkToken() is a way to set the LINK token address without knowing it's address. There is an on-chain contract (on specific chains) that has a pointer to a "link token contract" registry that points to the address of the LINK token on different chains. So this function gets the address by looking at this lookup table, then calls the setChainlinkToken function with this address.
You're then getting the error you specified, because the oracle contract you're interacting with doesn't know what the address of the LINK token is.
// if (_link == address(0)) {
// setPublicChainlinkToken();
// } else {
// setChainlinkToken(_link);
// }
// setPublicChainlinkToken();

Getting error while running test on the solidity code

This is the solidity code , a simple code provided in linkedin learning course -
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.7.0;
contract ApprovalContract{
address public sender;
address payable public receiver;
address public constant approver = 0x9BE32C0CB7910d71CA2c2a7D6B46ebd273dA01eC;
function deposit(address payable _receiver) external payable{
require(msg.value>0,"message smaller than 0");
sender = msg.sender;
receiver = _receiver;
}
function viewApprover() external pure returns(address){
return(approver);
}
function approve() external{
require(msg.sender == approver,"message is approved");
receiver.transfer(address(this).balance);
}
}
and this is the test code -
const ApprovalContract = artifacts.require('../contracts/ApprovalContract');
contract("ApprovalContract",function (accounts) {
it('initiates contract',async function(){
const contract = await ApprovalContract.deployed();
const approver = await contract.approver.call();
assert.equal(approver,0x9BE32C0CB7910d71CA2c2a7D6B46ebd273dA01eC,"approvers don't match");
});
it('takes a deposit',async function(accounts){
const contract = await ApprovalContract.deployed();
await contract.deposit(accounts[0],{value:1e+10,from:accounts[1]});
assert.equal(web3.eth.getBalance(contract.address),1e+10,"account did not match");
});
});
Keep getting the error whenever i run the test code using truffle test -
Error: invalid address (arg="_receiver", coderType="address", value=undefined)
Error: invalid address (arg="_receiver", coderType="address", value=undefined)
C:\Users\tanis\AppData\Roaming\npm\node_modules\truffle\node_modules\mocha\lib\runner.js:726
err.uncaught = true;
^
TypeError: Cannot create property 'uncaught' on string 'abort(Error: invalid address (arg="_receiver", coderType="address", value=undefined)). Build with -s ASSERTIONS=1 for more info.'
I learned the same course and encountered the same problem. it ended up working for me (but not sure exactly what the problem was).
Try connecting a meta mask like this:
ethereum.request({ method: 'eth_requestAccounts' });
also try several different sending and receiving addresses

buyTokens func in Crowdsale OpenZeppelin contract doesnt work with msg.value more then zero

I have Crowdsale contract written on the basis of OpenZepelin Crowdsale.sol
my contract:
contract MoonShardToken is StandardToken, Ownable {
string public name = "MyContract";
uint8 public decimals = 18;
string public symbol = "My";
/// this constructor added as a test
constructor() public {
totalSupply_ = (36000000 * (10 ** 18));
balances[msg.sender] = totalSupply_;
}
}
my crowdsale is copy of OpenZepelin Crowdsale.sol, i deploy my contract with truffle, i can console.log in tests my rate: 200000000000000
TotalSupply of my tokens: 3.6e+25, all functions in tests from contract works correctly, but when i use function buyTokens whith massage value more then zero i become error VM Exception while processing transaction: revert;when msg.value is zero i become no errors, and event in func emited
this is function buyTokens:
function buyTokens(address _beneficiary) public payable {
uint256 weiAmount = msg.value;
// _preValidatePurchase(_beneficiary, weiAmount); this is function with required msg.value>0 was commented for test
uint256 tokens = _getTokenAmount(weiAmount);
weiRaised = weiRaised.add(weiAmount);
_processPurchase(_beneficiary, tokens);
emit TokenPurchase(
msg.sender,
_beneficiary,
weiAmount,
tokens
);
_forwardFunds();
}
in truffle tests i use this function as: await Crowdsale.buyTokens(wallet, {from: wallet, value: web3.toWei(0.0001, "ether")});
wallet is account(1) with token balance 0. i use ganache cli and all my accs have ether? simple transaction works correctly.
When attempting buyTokens, this function calls _getTokenAmount(weiAmount) which returns weiAmount.mul(_rate). Can you post your migrations file? It may be that _rate is not set properly during deployment.

Having a Problem Testing my Solidity Smart Contract (w/ Truffle)

So Im building a basic NF Token. Created a basic minting function and mapping. Im testing the app with truffle, tried both solidity testing and JS testing. Having the following errors.
Using network 'development'.
Compiling ./contracts/NFCertificate.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/AddressUtils.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/introspection/ERC165.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/introspection/SupportsInterfaceWithLookup.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/math/SafeMath.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/ownership/Ownable.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/token/ERC721/ERC721Basic.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/token/ERC721/ERC721BasicToken.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/token/ERC721/ERC721Receiver.sol...
Compiling ./test/TestCertificate.sol...
Compiling truffle/Assert.sol...
Compiling truffle/DeployedAddresses.sol...
Compilation warnings encountered:
/Users/aditya/Desktop/Work & Hobbies/Ideas/Blockchain/Blockchain Development/Ethereum:dApp/CertificateContract/contracts/NFCertificate.sol:26:35: Warning: This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data.
uint256 tokenId = uint256(keccak256(certificateNum, msg.sender, title, message));
^---------------------------------------------------^
TestCertificate
1) testNumber
> No events were emitted
Contract: NFCertificate
2) It should return the same number
> No events were emitted
0 passing (1s)
2 failing
1) TestCertificate
testNumber:
Error: VM Exception while processing transaction: revert
at Object.InvalidResponse (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/errors.js:38:1)
at /usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/requestmanager.js:86:1
at /usr/local/lib/node_modules/truffle/build/webpack:/packages/truffle-provider/wrapper.js:134:1
at XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/httpprovider.js:128:1)
at XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:64:1)
at XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:354:1)
at XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:509:1)
at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:469:1)
at endReadableNT (_stream_readable.js:1081:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
2) Contract: NFCertificate
It should return the same number:
TypeError: instance.returnNumbers is not a function
at Context.<anonymous> (test/TestCertificate.js:9:31)
at /usr/local/lib/node_modules/truffle/build/webpack:/packages/truffle-core/lib/testing/testrunner.js:135:1
at /usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/property.js:119:1
at /usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/requestmanager.js:89:1
at /usr/local/lib/node_modules/truffle/build/webpack:/packages/truffle-provider/wrapper.js:134:1
at XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/httpprovider.js:128:1)
at XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:64:1)
at XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:354:1)
at XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:509:1)
at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:469:1)
at endReadableNT (_stream_readable.js:1081:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
The test scripts are running a simple internal function in the contract that returns an int = 1000 and compares that to the expected variable (let expected = 1000) declared in the test. Heres the JS test script
import assertRevert from "zeppelin-
solidity/test/helpers/assertRevert";
const NFCertificate = artifacts.require("NFCertificate");
contract("NFCertificate", () => {
it("It should return the same number", function() {
let instance = NFCertificate.deployed();
let expected = 1000;
assert.equal(instance.returnNumber(), expected);
});
});
Heres the Solidity Test Script:
pragma solidity ^0.4.20;
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/NFCertificate.sol";
contract TestCertificate {
function testNumber() public {
NFCertificate cert = NFCertificate(DeployedAddresses.NFCertificate());
uint expected = 1000;
Assert.equal(cert.returnNumber(), expected, "Numbers should be equal");
}
}
I also tried testing minted token ID's, and also owners of tokens based on the mapping I declared, Im getting the same problem. When writing a test contract in javascript it can't recognize the functions in the original NFT contract. When writing a test contract in solidity it almost always says "Error: VM Exception while processing transaction: revert" and nothing else.
Finally here's the contract im trying to test out. Any and all help is appreciated, im very new to coding and ethereum so I've probably made numerous mistakes.
pragma solidity ^0.4.24;
import '../node_modules/openzeppelin-solidity/contracts/token/ERC721/ERC721BasicToken.sol';
import '../node_modules/openzeppelin-solidity/contracts/ownership/Ownable.sol';
contract NFCertificate is ERC721BasicToken, Ownable {
struct Certificate {
uint certNum;
uint256 tokenId;
bytes32 title;
bytes32 message;
address owner;
}
mapping (uint256 => address) tokenToOwner;
mapping (address => uint256) ownerToToken;
mapping (uint256 => string) tokenIdToName;
event returnNumbers(uint number);
Certificate[] public certificates;
function createCert(bytes32 title, bytes32 message) public returns (bytes32){
uint certificateNum = certificates.length - 1;
uint256 tokenId = uint256(keccak256(certificateNum, msg.sender, title, message));
certificates.push(Certificate(certificateNum++, tokenId, title, message, msg.sender));
tokenToOwner[tokenId] = msg.sender;
ownerToToken[msg.sender] = tokenId;
_mint(msg.sender, tokenId);
}
function returnNumber() public returns(uint) {
uint number = 1000;
returnNumbers(number);
return number;
}
function whatTokensDoYouOwn(address owner) public view returns(uint256) {
return ownerToToken[owner];
}
}
NFCertificate.deployed() returns a promise, as does instance.returnNumber(). So the JS should be:
contract("NFCertificate", () => {
it("It should return the same number", async function() {
let instance = await NFCertificate.deployed();
let expected = 1000;
assert.equal(await instance.returnNumber(), expected);
});
});
As returnNumbers is an event, it should be emitted using the emit keyword. It's also good to style events to start with a capital, otherwise it might look like a function. So event ReturnNumbers(uint number);
function returnNumber() public returns(uint) {
uint number = 1000;
emit ReturnNumbers(number);
return number;
}
Adding the async/await lines should fix your JavaScript tests. If you later want to assert that your ReturnNumbers events were emitted correctly, I would suggest to use my truffle-assertions library, which includes functions to assert that events have or have not been emitted. It also includes functions to assert reverts and other failures in a straightforward way.