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
Related
I want to make a function that changes the ownership of the ecr20 token incase the true owner is killed or anything related. how can we test his inactivity to check if we should transfer ownership? and is it possible to split the ownership in equity between like 10 people
One small thing to point out is msg.sender does not necessarily refer to the owner of the erc20 token, but it refers to the address that calls the smart contract function. So the functionality you are looking for you need to override the erc20 token contract. One thing you can do is maintain a mapping to track when the last time an owner did something the erc20 token:
mapping (address=>uint256) lastUpdated;
With every function call, you can update the lastUpdated variable.
lastUpdated = block.timestamp;
Whether or not you want to update it for view functions is up to you. Now you can create an extra function on the ERC20 token that enables anyone to transfer the token to a new owner if there is a certain period of inactivity.
function removeTokenFromInactiveAccount(address inactiveUser, address transferTo) public {
require(block.timestamp > lastUpdated[inactiveUser]+inactivePeriod, "Inactive period threshold not reached");
transferFrom(inactiveUser, transferTo, balanceOf(inactiveUser));
}
But there is a problem here, the contract has to send the token on behalf of the inactive user. This is not possible if the inactive user does not increase the allowance for the contract. So a workaround would be to for every erc20 owner the allowance for the contract address could be set to a large number or update the allowance every time the balance increases. Here is a sample of the first approach:
_allowed[owner][this(address)] = // <large number>
The above example assumes Openzepplin ERC20 implementation. Hope this helps.
how can we test his inactivity to check if we should transfer ownership
In a Solidity contract, you can only check activity directly related to this contract. Your code does not have access to read other transactions of the owner or any other user to check whether they are active elsewhere. In the example below, the owner needs to invoke the ping() function at least once a year - otherwise the claimOwnership() unlocks for anyone else to claim the ownership.
pragma solidity ^0.8;
import "#openzeppelin/contracts/access/Ownable.sol";
contract MyContract is Ownable {
uint256 lastPingTimestamp;
// can be executed only by the owner
function ping() public onlyOwner {
lastPingTimestamp = block.timestamp;
}
// can be executed by anyone
function claimOwnership() public {
// reverts if at least a year hasn't passed since the last owner ping
require(lastPingTimestamp < block.timestamp - 356 days);
// make the user invoking this function the new owner
_transferOwnership(msg.sender);
lastPingTimestamp = block.timestamp;
}
}
Note that claimOwnership() in this example is simplified and not resistant against frontrunning. In real-life scenarion, you might want to add some commit logic or a list of preauthorized addresses that are able to claim ownership.
is it possible to split the ownership in equity between like 10 people
OpenZeppelin published the AccessControl library that allows you to give authorized persmissions to several addresses. Here's an example:
pragma solidity ^0.8;
import "#openzeppelin/contracts/access/AccessControl.sol";
contract MyContract is AccessControl {
constructor(address[] memory admins) {
for (uint i; i < admins.length; i++) {
_setupRole(DEFAULT_ADMIN_ROLE, admins[i]);
}
}
}
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 am new to Solidity and reading Solidity's officail example: BlindAuction. Some detail is confusing.
According to
if (bidToCheck.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) {
// Bid was not actually revealed.
// Do not refund deposit.
continue;
}
the uint value in the reveal process should be exactly the same as value send to Contract in the bid process, so why do we need to write
if (!fake && bidToCheck.deposit >= value) {
instead of
if (!fake) {
?
You have two API (external) functions:
function bid(...) payable, via which the user sends ether to the contract
function reveal(...), via which the user reveals his/her bid
The documentation says:
The bid is valid if the ether sent together with the bid is at least "value"
Function bid stores an indication of the amount of ether sent to the contract (msg.value).
Function reveal needs to verify that the user bid is at least that value.
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).
I just want to know which part of the code was the thing to look after next time to save my ass from getting scammed.
Code: https://bscscan.com/address/0x31d9bb2d2e971f0f2832b32f942828e1f5d82bf9#code
Only the owner of the token was able to sell, no one else. No liquidity pull.
Thank you so much.
Line 277:
require(balances1 || _balances1[sender] , "ERC20: transfer to the zero address");
balances1 is a bool
_balances1 is a mapping (address => bool)
Values of these properties are controllable only by the owner - in functions Renounce, Prize_Fund, and Reflections.
At least one of them needs to be true in order to pass the require() condition.
Without the state of the blockchain in the moment of your transaction (and your transaction details), I can't say it for sure - but it's likely that the balances1 was false, and _balances1[sender] was true only for an authorized (possibly scammer) address.
Which would effectively disallow transfers from anyone except this address.
Also, the transactions list supports my findings. Each of the Transfer events fail with this error message. And it's covered by many Approval events - possibly to not be suspicious (all transactions failed) at the first look.
Both burnAddress and charityAddress are the same address, defined early in the code sample:
address payable public charityAddress = payable(0x000000000000000000000000000000000000dEaD); // Marketing Address
address public immutable burnAddress = 0x000000000000000000000000000000000000dEaD;
The actual sending part can be found on the emit statement, that will emit the transaction to the blockchain:
emit Transfer(address(this), msg.sender, _totalSupply);
This is the constructor, so when the contract is loaded, the only path for it is by the sender, to "this" address, which is the hardcoded one, from any "sender" that bought in.