I'm new to solidity and I wanted to develop a subscription contract where a user can subscribe to a merchants plan and pay. But I'm unable to subscribe function and transfer the token to merchant.
I'm using open zeppelin ERC20 standard token to transfer.
IERC20 token = IERC20(plans[planId].token);
token.transferFrom(
payable(msg.sender),
payable(plan.merchant),
plan.amount
);
I don't know why but this keeps giving me allowance error even though I have increased the allowance of the user.
Since you're invoking the token.transferFrom() from the subscription contract, the token owner needs to increaseAllowance() for the subscription contract to manipulate their tokens.
Example:
Your subscription contract is deployed on address 0x123.
Token address is 0x456, and it has 18 decimals.
The user needs to execute increaseAllowance(0x123, 500 * 1e18) on the token contract in order to increase the allowance by 500 tokens.
Mind the subscription contract address as the first param, and the decimals as the second param (so the actual value passed to the second param is 500000000000000000000 because it includes the decimals as units as well).
Related
I have the following scenario:
I have a contract to generate a limited amount of erc20 tokens. User A buys X amount of this token. Then user A wants to sell some of his tokens, for X amount of ether, then user B wants to buy tokens of user A, how can I automatically transfer tokens from user A to user B when the transfer of ether from user B to user A has been successful be transfer?
Do I need a second contract to handle this kind of operation?
You may have two options,
Play around with Escrow SmartContracts (Like Openzeppelin) and modify it as per your need.
Use ERC20 Approve(spender,amount) on User B, to get allowance for your contract to spend on behalf of B. (spender : Your contract address)
Run a web3 script to listen on events to catch the corresponding transaction of sending ether from B->A ,
once the ether is transferred, you can place a function call to smart contract to spend the token from B to A
In your ERC20 Contract implementation, you can have a mapping of address -> eth, where the eth represents the selling price each user has set up.
Now, when a user "sells" their token, they can allow the same contract to transfer X amount of tokens from their balance which they want to sell.
And to sell, you can create a payable function that receives ether, and via parameter a seller address. This function will dynamically ( using the address received on the mapping we created at the beginning ) transfer X tokens to the buyer, using that seller's token price and the amount of ether received.
For example: If 1TKs = 0.5ETH, and the buyer sends 2eth, the contract will transfer 4TKS.
Recomendation.
Usually, the token contract and the seller/buyer functions are done in different contracts for security reasons, for example having the actual token, and the token shop separated on different contracts.
Disclaimer.
This is the simplest implementation I could think of, but it will accomplish your requirements.
Could ChainLink facilitate getting the current Ask/Bid price from DEX
like Binance and PancakeSwap?
"bidPrice" and "askPrice" on Binance
https://github.com/binance/binance-spot-api-docs/blob/master/rest-api.md#new-order--trade
"price" on PancakeSwap
https://github.com/pancakeswap/pancake-info-api/blob/develop/v2-documentation.md
Could you show an example of how to do this?
Thank you!
If the data is accessible via an API then you can use Chainlink Any-API calls to bring it into your smart contract
To do so, you need to know 3 things
The API endpoint that contains the data, and the inputs required
The outputs that the API returns, including their types (integer, string etc), as well as the path in the resulting JSON that contains the data you want
A Chainlink oracle on the network you're contract is on that has a compatible job that you can use (whether one you run yourself or someone elses)
Once you have these things, you can use the example consumer contract in the docs linked above, and then change the values to suit. ie here is an example contract that will make an API call to PancakeSwap to get the price of PancakeSwap token on BSC testnet:
1 - API address and inputs. In this case, according to your linked docs, the URL of the API call is https://api.pancakeswap.info/api/v2/tokens/0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82. The only input required is the token address in the URL
2 - We want the price, which is an integer and in the 'price' JSON element. We will multiply the price by 10**8 when we bring it on-chain because Solidity can't handle decimals
3 - Because this is a simple API call, we can use a community run CL node that takes a HTTP GET request, parses the JSON to find an element we specify, then multiplies the result and converts it to the type we want before returning it on-chain. Taking a look at the BSC testnet jobs on market.link, I found a suitable one here (GET, multiples result, returns a uint). From here we take the job ID and the oracle address, and note the cost in LINK required to use it
Now that we have all these details, we can modify the standard API consumer contract and put them all in, as follows. Changes I made include updating variables to reflect price instead of volume, also i changed the variables for job, oracle contract and fee, and i changed the setPublicChainlinkToken() method in the contructor to setChainlinkToken, specifically passing in the address of the LINK token on BSC testnet
pragma solidity ^0.8.7;
import "#chainlink/contracts/src/v0.8/ChainlinkClient.sol";
contract APIConsumer is ChainlinkClient {
using Chainlink for Chainlink.Request;
uint256 public price;
address private oracle;
bytes32 private jobId;
uint256 private fee;
constructor() {
setChainlinkToken(0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06);
oracle = 0x19f7f3bF88CB208B0C422CC2b8E2bd23ee461DD1;
jobId = "9b32442f55d74362b26c608c6e9bb80c";
fee = 0.0001 * 10 ** 18; // (Varies by network and job)
}
function requestPriceData() public returns (bytes32 requestId)
{
Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);
request.add("get", "https://api.pancakeswap.info/api/v2/tokens/0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82");
request.add("path", "price");
// Multiply the result by 1000000000000000000 to remove decimals
int timesAmount = 10**18;
request.addInt("times", timesAmount);
// Sends the request
return sendChainlinkRequestTo(oracle, request, fee);
}
function fulfill(bytes32 _requestId, uint256 _price) public recordChainlinkFulfillment(_requestId)
{
price = _price;
}
}
Once you compile and deploy, you then need to fund the contract with enough link to perform the request. You can get some testnet BSC LINK from the faucet, then transfer enough from your wallet to the deployed contract (in this case 0.001 LINK)
Once that's done you can execute the requestPriceData function, wait 30 secs then check the price getter function to see if you have a result. If you don't have a result after a while (1 min), it could mean the BSC node isn't up still. You can either run your own node, or use another network like Ethereum Kovan or Polygon Mumbai, which has many more active jobs
I managed already to write code interacting with Auto CAKE pool contract in order to get user balance. This can be done by interacting with bsc smart contract 0xa80240Eb5d7E05d3F250cF000eEc0891d00b51CC and calling userInfo function.
Hoewever, this function does not return the current balance but it returns the " cakeAtLastUserAction", which is the total number of CAKE deposited in this contract by the user. It doesn't include the CAKE rewards generated in-between.
What contract should be queried to get the number of CAKE rewards generated for a user with the Pancakeswap AutoCAKE pool?
im tryin to do a function inside my contract that when someone use it:
it get the tokenX_v1 balance of msg.sender,
send the same amount of tokenX_v2 from my contract,
send his tokenX_v1 to my contract or burn address.
part 1 and 2 i did it like this:
function query_oldBalance(address _adrs) view public returns (uint) {
address _tokenAddress = "tokenV1"
return IERC20(_tokenAddress).balanceOf(_adrs);
function myfunction() public {
_tokenTransfer(address(this),msg.sender,query_oldBalance(msg.sender) , false);
and until here it works as intended but now i need to remove tokenV1 from the msg.sender, and i thought to do a transfer to send it to the contract or the burn address, but when i try to do a transferFrom i get:
execution reverted: ERC20: transfer amount exceeds allowance even if i put the allowance to a much bigger number of what im trying to transfer
if i try with a normal transfer i got "execution reverted: Transfer amount exceeds the maxTxAmount. same here i tried to set the maxtxamount to a much bigger number than the token im trying to transfer.. about the allowance,
im not sure about how allowance and approve works and if i need it in this case but this is what i tried:
IERC20(_tokenAddress).allowance(msg.sender, address(this));
IERC20(_tokenAddress).approve(address(this),query_oldBalance(msg.sender)); //tried with this multiplied by 10 same story
i really don't understand how to do this addressA to addressB token transfer through contract.. Hope someone can help me Thanks.
IERC20(_tokenAddress).transferFrom(msg.sender, address(this), old_balance);
and before call this func the user should approve the address of the new token ON the old token contract
I am looking at this staking contract (pancake swap):
0x73feaa1ee314f8c655e354234017be2193c9e24e
and it's token (cake):
0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82
you can find a summary here:
https://bscscan.com/token/0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82?a=0x73feaa1ee314f8c655e354234017be2193c9e24e
On bscscan, I can get the following information:
price of token $12.54
market cap $2.9b
supply 231m
holders 137k
balance 88m (cake)
With nethereum, when I call:
web3.Eth.GetBalance.SendRequestAsync
I get:
with staking contract address: 479430015101300880
with token address: 3459819507903896496
and I'm not sure what the units are, nor how to map this to the information from bscscan.
I'm trying to get both the token value, but also what is the balance in the contract and I can't seem to find a way to do this.
so I looked at the nethereum playground and found an example dealing with ERC20 tokens, but when I put my addresses in it, the output is 0 and absolutely no error message, etc.