Solidity - API calls of AccuWeather on Chainlink do not function as expected - api

I am at the very beginning and am trying to understand how API calls exactly work. For this reason I am trying to deploy and make calls with the code posted by AccuWeather on chainlink market.
The code:
https://market.link/nodes/AccuWeather/integrations#CurrentConditionsResult
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
import "#chainlink/contracts/src/v0.8/ChainlinkClient.sol";
contract AccuweatherConsumer is ChainlinkClient {
using Chainlink for Chainlink.Request;
/* ========== CONSUMER STATE VARIABLES ========== */
struct RequestParams {
uint256 locationKey;
string endpoint;
string lat;
string lon;
string units;
}
struct LocationResult {
uint256 locationKey;
string name;
bytes2 countryCode;
}
// Maps
mapping(bytes32 => LocationResult) public requestIdLocationResult;
mapping(bytes32 => RequestParams) public requestIdRequestParams;
/* ========== CONSTRUCTOR ========== */
/**
* #param _link the LINK token address.
* #param _oracle the Operator.sol contract address.
*/
constructor(address _link, address _oracle) {
setChainlinkToken(_link);
setChainlinkOracle(_oracle);
}
/* ========== CONSUMER REQUEST FUNCTIONS ========== */
/**
* #notice Returns the location information for the given coordinates.
* #param _specId the jobID.
* #param _payment the LINK amount in Juels (i.e. 10^18 aka 1 LINK).
* #param _lat the latitude (WGS84 standard, from -90 to 90).
* #param _lon the longitude (WGS84 standard, from -180 to 180).
*/
function requestLocation(
bytes32 _specId,
uint256 _payment,
string calldata _lat,
string calldata _lon
) public {
Chainlink.Request memory req = buildChainlinkRequest(_specId, address(this), this.fulfillLocation.selector);
req.add("endpoint", "location"); // NB: not required if it has been hardcoded in the job spec
req.add("lat", _lat);
req.add("lon", _lon);
bytes32 requestId = sendChainlinkRequest(req, _payment);
// Below this line is just an example of usage
storeRequestParams(requestId, 0, "location", _lat, _lon, "");
}
/* ========== CONSUMER FULFILL FUNCTIONS ========== */
/**
* #notice Consumes the data returned by the node job on a particular request.
* #dev Only when `_locationFound` is true, both `_locationFound` will contain meaningful data (as bytes). This
* function body is just an example of usage.
* #param _requestId the request ID for fulfillment.
* #param _locationFound true if a location was found for the given coordinates, otherwise false.
* #param _locationResult the location information (encoded as LocationResult).
*/
function fulfillLocation(
bytes32 _requestId,
bool _locationFound,
bytes memory _locationResult
) public recordChainlinkFulfillment(_requestId) {
if (_locationFound) {
storeLocationResult(_requestId, _locationResult);
}
}
/* ========== PRIVATE FUNCTIONS ========== */
function storeRequestParams(
bytes32 _requestId,
uint256 _locationKey,
string memory _endpoint,
string memory _lat,
string memory _lon,
string memory _units
) private {
RequestParams memory requestParams;
requestParams.locationKey = _locationKey;
requestParams.endpoint = _endpoint;
requestParams.lat = _lat;
requestParams.lon = _lon;
requestParams.units = _units;
requestIdRequestParams[_requestId] = requestParams;
}
function storeLocationResult(bytes32 _requestId, bytes memory _locationResult) private {
LocationResult memory result = abi.decode(_locationResult, (LocationResult));
requestIdLocationResult[_requestId] = result;
}
}
I have deployed the contract, fueled it with LINKs. I can do the calls for the Location by entering the JobID, lat and long I found an AccuWeather (lat: 30.918 and long:-99.786) as well as the link payment. The call seems to be successful but when I take the requestID and use it to see the LocationResult I receive empty values.
I dont really know why it does not work or weather I forget to do something in between.
If I understand it correctly I need the LocationResult function to get information required for the fulfill function, is that correct?
I just hope someone faced the same problem and can help me. I would be very thankful for any suggestion!!

Related

Transaction failed with execution error while call Function

I am receiving the following message:
"Warning! Error encountered during contract execution [execution reverted]"
What I'm trying to do is simple, I have a contract, where I don't get token, I just use ethereum and users just pay gas fee to miners.
What I'm trying to do here is call a contract function, but it adds data to the blockchain, which wastes gas.
Here's the contract:
https://goerli.etherscan.io/address/0xa46dc78595315b94904182013888adb439c6009f
Contract Code:
/**
* #title Ballot
* #dev Implements voting process along with vote delegation
*/
contract Ballot is IHelper, Guard, Logging {
Confirmed[6] private _confirmedVotes;
Abstention private _abstentionVotes;
uint[6] private _candidates;
uint private _totalConfirmedVotes;
mapping(address => bool) private _electorHasAlreadyVoted;
constructor() {
_registerCandidates();
emit LogStartElection("Beginning of the election period, ballot box released!", getResult());
}
/** #dev Register Candidates **/
function _registerCandidates() private {
for (uint i = 0; i < _candidates.length; i++) {
_candidates[i] = i;
_confirmedVotes[i].candidate = i;
}
}
/**
* #dev Return Elector Has Already Voted
* #return value of '_electorHasAlreadyVoted'
*/
function getElectorHasAlreadyVoted() public view returns (bool) {
return _electorHasAlreadyVoted[msg.sender];
}
/**
* #dev Return Electoral Result
* #return value of 'ElectionResult'
*/
function getResult() public view returns (ElectionResult memory) {
return
ElectionResult({
candidates: _candidates,
totalConfirmedVotes: _totalConfirmedVotes,
confirmedVotes: _confirmedVotes,
abstentionVotes: _abstentionVotes
});
}
/**
* #dev Elector Vote Confirmation
* #param candidateID value to store
*/
function confirmVote(
uint candidateID
) public onlyCandidateRegistered(candidateID, _candidates.length) onlyElectorWhoDidNotVote(_electorHasAlreadyVoted[msg.sender]) {
_confirmedVotes[candidateID].totalVotes++;
_confirmedVotes[candidateID].elector.push(msg.sender);
_confirmedVotes[candidateID].candidate = candidateID;
_electorHasAlreadyVoted[msg.sender] = true;
_totalConfirmedVotes++;
emit LogElectorVote("Vote Confirmed and Computed!", getResult());
}
/** #dev Elector Vote Abstention **/
function abstainVote() public onlyElectorWhoDidNotVote(_electorHasAlreadyVoted[msg.sender]) {
_abstentionVotes.totalVotes++;
_abstentionVotes.elector.push(msg.sender);
_electorHasAlreadyVoted[msg.sender] = true;
emit LogElectorVote("Vote Abstained and Computed!", getResult());
}
}
DApp Ethers code:
const PROVIDER = ethers.providers.InfuraProvider.getWebSocketProvider({ chainId: 5, name: 'goerli' });
const PRIVATE_WALLET = new ethers.Wallet(process.env.REACT_APP_WALLET_PRIVATE_KEY || '', PROVIDER);
const CONTRACT = new ethers.Contract(
process.env.REACT_APP_SOLIDITY_CONTRACT_ADDRESS || '',
BallotContract.abi,
PRIVATE_WALLET
)
const ELECTOR_SIGNER = CONTRACT.connect(ELECTOR_WALLET);
const CONTRACT_ADDRESS = await infura.contract.resolvedAddress;
const GAS_LIMIT = await ELECTOR_SIGNER.estimateGas.confirmVote(1);
const TRANSACTION_HASH = await window.ethereum?.request({
method: 'eth_sendTransaction',
params: [
{
from: ELECTOR_SIGNER,
to: CONTRACT_ADDRESS,
gas: estimateGas._hex,
value: 0,
},
],
})
const TRANSACTION_RECEIPT = await PROVIDER.waitForTransaction(TRANSACTION_HASH);
const RESPONSE = await ELECTOR_SIGNER.confirmVote(1);
For a contract to accept ETH (or generally native tokens - BNB on Binance Smart Chain, MATIC on Polygon, ...), it needs to implement either of the special functions - receive() or payable fallback(). If the contract doesn't implement any of these functions, it rejects the incoming transfer.
contract Ballot {
// ...
receive() external payable {
// can be empty; or you can redirect the incoming transfer to an EOA
}
}
When you just send empty value and empty data, it tries to invoke the fallback() function, that is also not present. So the solution is similar in this case - implement the fallback() special function.
contract Ballot {
// ...
fallback() external payable {
// can be empty
}
}

TypeError: Contract "ERC721Enumerable" should be marked as abstract

So I have this error that says (TypeError: Contract "ERC721Enumerable" should be marked as abstract.) and I am unaware on how should I mark the smart contract as abstract. I'm still an absolute beginner so I have no clue how to do certain things yet.
I think I've had this problem before though I have forgotten how I solved it since that was a long time ago and is out of the range of what I can remember.
also here is the program:
pragma solidity ^0.8.0;
import './ERC721.sol';
contract ERC721Enumerable is ERC721 {
uint256[] private _allTokens;
// CHALLENGE! Write out mapping yourself!!
// mapping from tokenId to position in _allTokens array
mapping(uint256 => uint256) private _allTokensIndex;
// mapping of owner to list of all owner token ids
mapping(address => uint256[]) private _ownedTokens;
// mapping from token ID index of the owner tokens list
mapping(uint256 => uint256) private _ownedTokensIndex;
// #notice count NFTs tracked by this contract
// #return A count of valid NFTs tracked by this contract, where each on of
// them has an assigned and queryable ower not equal to the zero address
// #notice Enumerate valid NFT's
// #dev Throws if '_index" >= 'totalSupply()'.
// #param _index A couter less than 'totalSupply()'
// #return The token identifier for the '_index'th NFt,
// (sort order not specified)
//function tokenByIndex(uint256 _index) external view returns (uint256);
// #notice Enumerate NFTs assigned to an owner
// #dev Throws if '_index' >= 'balanceOf(_owner)' or if
// '_owner' is the zero address, representing invalid NFTs.
// #param _owner An address where we are interested in NFTs owned by them
// #param _index A counter less than 'balanceOf(_owner)'
// #return The token identifier for the '_index'th NFT assigned to '_owner',
// (sort order not specfied)
//function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
function _mint(address to, uint256 tokenId) internal override(ERC721) {
super._mint(to, tokenId);
// 2 things!
// a. add tokens too the owner
// b. all tokens to out totalSupply - allToken
_addTokensToAllTokenEnumeration(tokenId);
_addTokensToOwnerEnumeration(to, tokenId);
}
// add tokens to the _allTokens array and set the position of the tokens indexes
function _addTokensToAllTokenEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
// two function - one that returns token by the index
// another one thata retruns tokenByOwnerIndex
function tokenByIndex(uint256 index) public view returns(uint256) {
// make sure that the undex is not our of bounds of the
// total supply
require(index < totalSupply(), 'global index is out of bounds!');
return _allTokens[index];
}
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256){
require(index < balanceOf(owner), 'owner is out of bounds!');
return _allTokens[index];
}
// return the total supply of the _allTokens array
function totalSupply() public view returns(uint256) {
return _allTokens.length;
}
function _addTokensToOwnerEnumeration(address to, uint256 tokenId) public {
_ownedTokensIndex[tokenId] = _ownedTokens[to].length;
_ownedTokens[to].push(tokenId);
}
// #notice Transfer owner ship of an NFT -- THE REAL CALLER IS RESPOSIBLE
// TO CONFIRM THAT '_to' IS CAPABLE OF RECEIVING NFTS OR ELSE
// THEY MAY BE PERMANENTLY LOST
// #dev Throws untess 'msg.sender' is the current owner, an authorized
// operator, or the approved address for this NFT. Throws if '_from' is
// not current owner, Throws if '_to' is the zero address. Throws if
// '_tokenId' is not a valid NFT.
// #param _from The current owner of the NFT
// #param _to the new owner
// #param _tokenId The NFT to transfer
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
} ```
Your contract not fully implement all the functions of the ERC721 contract..
Refer
https://ethereum.stackexchange.com/questions/112724/error-contract-should-be-marked-as-abstract
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol

How can I multiply dates in Solidity after Safemath.sol library is deprecated

I had this piece of code compiling in Solidity 0.6.0 without errors(I'm using Remix). But suddenly SafeMath library got deprecated because it wasn't necessary to import it anymore and I don't know how to fix this line:
uint raiseUntil = now.add(durationInDays.mul(1 days));
where I calculate a future date using the ¨mul¨ function.
I let you all code below. It's the backend of a crowdfunding platform. The raisedUntil variable is the date where the deadline of the crowdfunding project ends.
pragma solidity 0.6.0;
// Importing OpenZeppelin's SafeMath Implementation
import 'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/SafeMath.sol';
contract Crowdfunding {
using SafeMath for uint256;
// List of existing projects
Project[] private projects;
// Event that will be emitted whenever a new project is started
event ProjectStarted(
address contractAddress,
address projectStarter,
string projectTitle,
string projectDesc,
uint256 deadline,
uint256 goalAmount
);
/** #dev Function to start a new project.
* #param title Title of the project to be created
* #param description Brief description about the project
* #param durationInDays Project deadline in days
* #param amountToRaise Project goal in wei
*/
function startProject(
string calldata title,
string calldata description,
uint durationInDays,
uint amountToRaise
) external {
uint raiseUntil = now.add(durationInDays.mul(1 days));
Project newProject = new Project(msg.sender, title, description, raiseUntil, amountToRaise);
projects.push(newProject);
emit ProjectStarted(
address(newProject),
msg.sender,
title,
description,
raiseUntil,
amountToRaise
);
}
/** #dev Function to get all projects' contract addresses.
* #return A list of all projects' contract addreses
*/
function returnAllProjects() external view returns(Project[] memory){
return projects;
}
}
contract Project {
using SafeMath for uint256;
// Data structures
enum State {
Fundraising,
Expired,
Successful
}
// State variables
address payable public creator;
uint public amountGoal; // required to reach at least this much, else everyone gets refund
uint public completeAt;
uint256 public currentBalance;
uint public raiseBy;
string public title;
string public description;
State public state = State.Fundraising; // initialize on create
mapping (address => uint) public contributions;
// Event that will be emitted whenever funding will be received
event FundingReceived(address contributor, uint amount, uint currentTotal);
// Event that will be emitted whenever the project starter has received the funds
event CreatorPaid(address recipient);
// Modifier to check current state
modifier inState(State _state) {
require(state == _state);
_;
}
// Modifier to check if the function caller is the project creator
modifier isCreator() {
require(msg.sender == creator);
_;
}
constructor
(
address payable projectStarter,
string memory projectTitle,
string memory projectDesc,
uint fundRaisingDeadline,
uint goalAmount
) public {
creator = projectStarter;
title = projectTitle;
description = projectDesc;
amountGoal = goalAmount;
raiseBy = fundRaisingDeadline;
currentBalance = 0;
}
/** #dev Function to fund a certain project.
*/
function contribute() external inState(State.Fundraising) payable {
require(msg.sender != creator);
contributions[msg.sender] = contributions[msg.sender].add(msg.value);
currentBalance = currentBalance.add(msg.value);
emit FundingReceived(msg.sender, msg.value, currentBalance);
checkIfFundingCompleteOrExpired();
}
/** #dev Function to change the project state depending on conditions.
*/
function checkIfFundingCompleteOrExpired() public {
if (currentBalance >= amountGoal) {
state = State.Successful;
payOut();
} else if (now > raiseBy) {
state = State.Expired;
}
completeAt = now;
}
/** #dev Function to give the received funds to project starter.
*/
function payOut() internal inState(State.Successful) returns (bool) {
uint256 totalRaised = currentBalance;
currentBalance = 0;
if (creator.send(totalRaised)) {
emit CreatorPaid(creator);
return true;
} else {
currentBalance = totalRaised;
state = State.Successful;
}
return false;
}
/** #dev Function to retrieve donated amount when a project expires.
*/
function getRefund() public inState(State.Expired) returns (bool) {
require(contributions[msg.sender] > 0);
uint amountToRefund = contributions[msg.sender];
contributions[msg.sender] = 0;
if (!msg.sender.send(amountToRefund)) {
contributions[msg.sender] = amountToRefund;
return false;
} else {
currentBalance = currentBalance.sub(amountToRefund);
}
return true;
}
/** #dev Function to get specific information about the project.
* #return Returns all the project's details
*/
function getDetails() public view returns
(
address payable projectStarter,
string memory projectTitle,
string memory projectDesc,
uint256 deadline,
State currentState,
uint256 currentAmount,
uint256 goalAmount
) {
projectStarter = creator;
projectTitle = title;
projectDesc = description;
deadline = raiseBy;
currentState = state;
currentAmount = currentBalance;
goalAmount = amountGoal;
}
}
You might decide to switch to a newer version of Solidity (current is 0.8.4), where now is deprecated so I already used block.timestamp instead. It's the same thing - now was just its alias.
The SafeMath library checks whether an arithmetic operation (such as multiplication or addition) on two unsigned integers would overflow/underflow. If it would, it throws an exception. If it wouldn't, it performs the arithmetic operation. Since Solidity 0.8 this is done automatically and SafeMath is not needed, so another reason to use the current version.
In Solidity 0.8 and newer, if this would overflow, it would throw an exception automatically
uint raiseUntil = block.timestamp + durationInDays * 1 days;
In older versions, you'll need to check for the possible overflow yourself and throw the exception from your code (the same behavior as SafeMath would do).
uint durationInSeconds = durationInDays * 1 days;
// Check that the result of division (inverse operation to multiplication) is the original number.
// If it's not, throw an exception, because the multiplication overflowed.
require(durationInSeconds / durationInDays == 1 days, 'Multiplication overflow');
uint raiseUntil = block.timestamp + durationInSeconds;
// Check that the result of subtraction (inverse operation to addition) is the original number.
// If it's not, throw an exception, because the addition overflowed.
require(raiseUntil - block.timestamp == durationInSeconds, 'Addition overflow');
Integer overflow/underflow is one of the most common security vulnerabilities in smart contracts. If your startProject() function was vulnerable, it would only allow to start a project with a deadline in the past. But in other implementations it can have more serious consequences. For example if an attacker exploits this vulnerability on a token contract, it could allow them to spend more tokens than they own.

Access to inherited variable in solidity to overwrite it

I want to override the following inherited function:
function _setBaseURI(string memory baseURI) public override(ERC721Full, ERC721Metadata) {
_baseURI = baseURI;
}
The problem is that it gives me the error Undeclared Identifier with _baseURI.
The variable was implemented private. Is it for that reason that it cannot be overwritten? And if so, why can the function be?
My contract:
pragma solidity ^0.6.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0-beta.0/contracts/token/ERC721/ERC721Full.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0-beta.0/contracts/drafts/Counters.sol";
contract GameItem is ERC721Full {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor() ERC721Full("GameItem", "ITM") public {
}
function awardItem(address player, string memory tokenURI) public returns (uint256) {
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(player, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
function _setBaseURI(string memory baseURI) public override(ERC721Full, ERC721Metadata) {
_baseURI = baseURI;
}
}
The Heritage
pragma solidity ^0.6.0;
import "../../GSN/Context.sol";
import "./ERC721.sol";
import "./IERC721Metadata.sol";
import "../../introspection/ERC165.sol";
contract ERC721Metadata is Context, ERC165, ERC721, IERC721Metadata {
// Token name
string private _name;
// Token symbol
string private _symbol;
// Base URI
string private _baseURI;
// Optional mapping for token URIs
mapping(uint256 => string) private _tokenURIs;
/*
* bytes4(keccak256('name()')) == 0x06fdde03
* bytes4(keccak256('symbol()')) == 0x95d89b41
* bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
*
* => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
*/
bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
/**
* #dev Constructor function
*/
constructor (string memory name, string memory symbol) public {
_name = name;
_symbol = symbol;
// register the supported interfaces to conform to ERC721 via ERC165
_registerInterface(_INTERFACE_ID_ERC721_METADATA);
}
/**
* #dev Gets the token name.
* #return string representing the token name
*/
function name() external view override returns (string memory) {
return _name;
}
/**
* #dev Gets the token symbol.
* #return string representing the token symbol
*/
function symbol() external view override returns (string memory) {
return _symbol;
}
/**
* #dev Returns the URI for a given token ID. May return an empty string.
*
* If the token's URI is non-empty and a base URI was set (via
* {_setBaseURI}), it will be added to the token ID's URI as a prefix.
*
* Reverts if the token ID does not exist.
*/
function tokenURI(uint256 tokenId) external view override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
// Even if there is a base URI, it is only appended to non-empty token-specific URIs
if (bytes(_tokenURI).length == 0) {
return "";
} else {
// abi.encodePacked is being used to concatenate strings
return string(abi.encodePacked(_baseURI, _tokenURI));
}
}
/**
* #dev Internal function to set the token URI for a given token.
*
* Reverts if the token ID does not exist.
*
* TIP: if all token IDs share a prefix (e.g. if your URIs look like
* `http://api.myproject.com/token/<id>`), use {_setBaseURI} to store
* it and save gas.
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
/**
* #dev Internal function to set the base URI for all token IDs. It is
* automatically added as a prefix to the value returned in {tokenURI}.
*
* _Available since v2.5.0._
*/
function _setBaseURI(string memory baseURI) internal virtual {
_baseURI = baseURI;
}
/**
* #dev Returns the base URI set via {_setBaseURI}. This will be
* automatically added as a preffix in {tokenURI} to each token's URI, when
* they are non-empty.
*
* _Available since v2.5.0._
*/
function baseURI() external view returns (string memory) {
return _baseURI;
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
if (to == address(0)) { // When burning tokens
// Clear metadata (if any)
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
}
}
}
It's a visibility issue.
If you want to access the _baseURI property in a derived contract, you need to make it at least internal (it's currently private).
Which also means copying a set of contracts locally so that you can update the ERC721Metadata.sol and import the updated version (and not the remote version) from the other contracts.
The _setBaseURI() function alone can be overridden because it's visible from your contract.
Private functions and state variables are only visible for the contract they are defined in and not in derived contracts.
Cannot access private property in a derived contract.
Source of the quote: https://docs.soliditylang.org/en/v0.8.3/contracts.html#visibility-and-getters

Error: Invalid number of arguments to Solidity function in simple crowdsale contract

I am a beginner on smart contract development. I am using openZeppelin, truffle and Ganache to develop some really basic token and crowdsale contract. I came across an error when I tried to call the buytoken() method from the crowdsale contract in Truffle console . Can someone help me solve the problem? There is no problem when migrating and deploying the contract.
contract Crowdsale {
using SafeMath for uint256;
// The token being sold
ERC20 public token;
// Address where funds are collected
address public wallet;
// How many token units a buyer gets per wei.
// The rate is the conversion between wei and the smallest and indivisible token unit.
// So, if you are using a rate of 1 with a DetailedERC20 token with 3 decimals called TOK
// 1 wei will give you 1 unit, or 0.001 TOK.
uint256 public rate;
// Amount of wei raised
uint256 public weiRaised;
/**
* Event for token purchase logging
* #param purchaser who paid for the tokens
* #param beneficiary who got the tokens
* #param value weis paid for purchase
* #param amount amount of tokens purchased
*/
event TokenPurchase(
address indexed purchaser,
address indexed beneficiary,
uint256 value,
uint256 amount
);
/**
* #param _rate Number of token units a buyer gets per wei
* #param _wallet Address where collected funds will be forwarded to
* #param _token Address of the token being sold
*/
constructor(uint256 _rate, address _wallet, ERC20 _token) public {
require(_rate > 0);
require(_wallet != address(0));
require(_token != address(0));
rate = _rate;
wallet = _wallet;
token = _token;
}
// -----------------------------------------
// Crowdsale external interface
// -----------------------------------------
/**
* #dev fallback function ***DO NOT OVERRIDE***
*/
function () external payable {
}
/**
* #dev low level token purchase ***DO NOT OVERRIDE***
* #param _beneficiary Address performing the token purchase
*/
function buyTokens(address _beneficiary, uint256 amount) public payable {
uint256 weiAmount = amount.mul(rate);
token.transfer(_beneficiary, weiAmount);
}
The truffle console command is listed below:
myToken.deployed().then(function(i){BT = i})
myCrowdsale.deployed().then(function(i){BTC = i})
BT.transferOwnership(BTC.address)
purchaser = web3.eth.accounts[2]
BTC.buyTokens(purchaser,web3.toWei(5, "ether") )
When implementing a payable the amount paid must not be an argument, but instead it will be available at msg.value. Otherwise you're not sending any ether, and/or can be exploited, if I call the method with: 5 ether as amount but I only send 1 wei.
function buyTokens(address _beneficiary) public payable {
uint256 weiAmount = msg.value.mul(rate);
token.transfer(_beneficiary, weiAmount);
}
Furthermore, if the beneficiary address is the same that buys the token, you can use: msg.sender
And the method must be called like this:
BTC.buyTokens(purchaser, { value: web3.toWei(5, "ether"), from: purchaser });
or using msg.sender
BTC.buyTokens({ value: web3.toWei(5, "ether"), from: purchaser });
If you don't use: from the ethers will be sent by the default account, which is not purchaser in your case.