Is it possible in Solidity to compare
LastTransactionPrice with CurrentAsk & CurrentBid?
then
Disable Buying/Selling if the price (Ask/Bid) is below LastTransactionPrice?
Thank you!
You create 3 state variables for CurrentAsk, CurrentBid and LastTransactionPrice:
uint256 CurrentAsk private;
uint256 CurrentBid private;
uint256 LastTransactionPrice private;
then write to setters to mutate those two state variables:
// askPrice gets set by the seller
function setCurrentAsk(uint256 askPrice) public {
CurrentAsk=askPrice
}
// bidPrice gets set by the buyer
function setCurrentBid(uint256 bidPrice) public {
CurrentBid=bidPrice
}
You can write a require statement to add buying/selling function but in this way, people still can call setCurrentAsk and setCurrentBid functions and pay gas fees. To be more efficient, you add require statements to both functions.
function setCurrentAsk(uint256 askPrice) public {
require(askPrice>LastTransactionPrice,"ask higher amount")
CurrentAsk=askPrice
}
function setCurrentBid(uint256 bidPrice) public {
require(bidPrice > LastTransactionPrice, "ask higher amount")
CurrentBid=bidPrice
}
require statement will check the current condition and if does not return true, it will revert the function execution and solidity will show the error that you defined: "ask higher amount"
Related
// contracts/transferownership.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract transferownership is ERC20, Ownable {
uint256 lastpresence;
uint256 amount = balanceOf(msg.sender);
constructor(uint256 initialSupply) ERC20("interorm", "intr") {
_mint(msg.sender, initialSupply);
}
function presence() public onlyOwner {
lastpresence = block.timestamp;
}
function changeOwnership(address newowner) public {
require(lastpresence < block.timestamp - 356 days);
transfer(newowner, amount);
_transferOwnership(newowner);
lastpresence = block.timestamp;
}
}
//The transaction has been reverted to the initial state.
Reason provided by the contract: "ERC20: transfer amount exceeds balance".
Debug the transaction to get more information.
//basically the program should transfer the whole amount of money
and then change ownership but im getting this error
everytime i call the changeownership function
To fix it, simply declare the amount variable in the changeOwnership function. That is before you call the transfer method.
uint256 amount = balanceOf(msg.sender);
transfer(newowner, amount);
Ensure that you set the changeOwnership function as payable.
function changeOwnership(address newowner) payable public {
Explanation: When you debug the function, the way you have it originally, you will find that the value=0, this is because the amount declaration in the global variable is not called in the stack when the transfer method is called.
To make the amount available in the call stack, you will have to parse it in the function.
could anyone help me with this??
used online remix in order to create a calucator using following criteria
Add Log of transactions using the event/emit
Each time one of the methods is called you will add
the address (msg.sender)
the action (“add”, “subtract”…)
the number
ii. Create a modifier “isOwner” like we did in class and add it to all the
methods in the calculator.
iii. Add a check using require or revert for the divide method to make sure
you are not dividing by zero (0).
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
contract Calculator{
mapping(address => uint256) public transactions;
address public owner;
address[] public transList; //// Showing to modify this line of code
constructor() {
owner = msg.sender;
}
modifier isOwner() {
require(msg.sender == owner, "Sender is not Owner");
_;
}
function whoIsOwner() public isOwner view returns (address) {
return owner;
}
uint256 public total =0;
uint256 public current_total =0;
function add(uint256 _amount) isOwner public{
total = total + _amount;
transList.push(msg.sender);
transList.push("add"); /// Error in this line
transList.push(_amount);
}
I have been written a smart contract, I am trying to execute the following code but I have these problems:
1- "Gas requirement of function EKM.register_PK is infinite: If the gas requirement of a function is higher than the block gas limit, it cannot be executed. Please avoid loops in your functions or actions that modify large areas of storage (this includes clearing or copying arrays in storage)
Pos: 32:0:"
2- "Use "assert(x)" if you never ever want x to be false, not in any circumstance (apart from a bug in your code). Use "require(x)" if x can be false, due to e.g. invalid input or a failing external component.
more
Pos: 30:2:"
My code:
pragma solidity >=0.8.13;
//SPDX-License-Identifier:MIT
contract EKM{
/**
* #dev VTA is a state variable
*/
address public VTA;
/**
* #dev mapping address as key to struct user with mapping name users
*/
mapping (uint => user) public users;
/**
* #dev assigning the contract deployer as the VTA
*/
constructor() {
VTA =msg.sender;
}
struct user {
string PKname;
string PKvehicle;
uint256 vP;
bool status;
}
event addPK(string name, string PKv, uint256 VPv) ;
function register_PK(uint ID_v, string memory PKname, string memory PKvehicle, uint256 vP) public returns(bool){
require(users[ID_v].status == true,"register the public key of the user");
if(msg.sender != VTA)
{revert();}
if(ID_v == 0)
{return false;}
else
{
ID_v++;
users[ID_v]= user(PKname,PKvehicle,vP,true);
//PKname=users[ID_v].PKname;
//PKvehicle=users[ID_v].PKvehicle;
// vP=users[ID_v].vP;
emit addPK(PKname, PKvehicle, vP);
return true;
}
}
}
what should I do?
Go to solidity static analysis ,and then gas and economy , untick all options except. This on local calls:
Invocation of local functions via 'this' and Delete dynamic array:
Use require/assert to ensure complete deletion. it will work
Is it possible for the same contract to handle multiple ERC721 tokens? And if so, how?
Let’s say you’re making a game and you need to track two types of ERC721 tokens: unique Weapons and unique Vehicles.
You could have Structs for them, as follows:
struct Weapon {
uint256 IDNumber;
string type; // Sword, Bow&Arrow, Gun, Rifle, etc.
string specialFeature;
}
struct Vehicle {
uint256 IDNumber;
string type; // Car, Airplane, Boat, Spaceship, etc.
uint256 damageFactor;
}
To track their ownership, you could double the arrays managing them - for example instead of having the standard:
// Enumerable mapping from token ids to their owners
EnumerableMap.UintToAddressMap private _tokenOwners;
You would do:
// Enumerable mapping from token ids to their owners
EnumerableMap.UintToAddressMap private _weaponTokenOwners;
EnumerableMap.UintToAddressMap private _vehicleTtokenOwners;
(This may not be the most elegant way, but it's a start.)
The real question though is: how would you handle mandatory functions that are part of the ERC721 standard, such as balanceOf() and ownerOf()?
To be specific, are you allowed to say add an additional argument to these methods’ signatures to help indicate which particular Token you’re querying about?
For example, instead of this:
function balanceOf(address owner) public view override returns (uint256) {
}
You’d add a tokenName argument to the function’s signature, as follows:
function balanceOf(address owner, string tokenName) public view override returns (uint256) {
if(tokenName == “weapon”) {
return ownerAndHisWeaponTokensDictionary[owner].length;
}
else if(tokenName == “vehicle”) {
return ownerAndHisVehicleTokensDictionary[owner].length;
}
}
And you’d do something similar for ownerOf()?
Is this allowable?
And is this even the right approach tackling this - or is there a different way to reason about all of this and approach it differently?
My approach would be to define 3 separate contracts on 3 separate addresses:
address 0x123123 as the Weapons ERC-721 token contract
address 0x456456 as the Vehicles ERC-721 token contract
address 0x789789 as the actual game contract
In the game contract, you can then call the NFTs contracts to get or validate values:
function attack(uint attackerWeaponId) {
require(weaponsContract.isOwnerOf(msg.sender, attackerWeaponId));
// ...
}
The isOwnerOf() function takes 2 arguments, address owner and uint256 weaponId. Also, a user can probably own more weapons so that's why I'm showing the validation.
And the weapons contract balanceOf(address) would reflect the total amount of the Weapon NFTs that the user has.
mapping (address => Weapon[]) userOwnedWeapons;
function balanceOf(address owner) external view returns (uint256) {
return userOwnedWeapons[msg.sender].length;
}
I have a problem related to refund the users entered inside the solidity contract. I don't, have any idea if is possible iterate all the players of my contract and refund all of them with all the balance.I read in some tutorials, iterate inside the solidity contract cost a lot of gas depends of the numer of iterations.
contract Lottery{
address payable public manager;
string public name; // short name (up to 32 bytes)
address [] players;
uint256 nTickets;
address winner;
bool enable;
uint256 minimunContribution;
mapping(address => uint) public balances;
constructor (string memory LotteryName, uint minimun, address payable creator) public {
manager = creator;
name = LotteryName;
winner = address(0);
enable = true;
minimunContribution = minimun;
}
modifier restricted() {
require(msg.sender == manager, "Access forbidden");
_;
}
function enterInToLottery() public payable {
require(msg.value > minimunContribution && enable == true, "Insufficient funds to allow transfer");
players.push(msg.sender);
balances[msg.sender] += msg.value;
nTickets++;
}
//this function refund
function paybackEther(bool newfinished) public restricted {
enable = !newfinished;
selfdestruct(msg.sender);
}}
Thanks in advance to all.
Yes that can be problematic as it will use a lot of gas and may even hit limits. To solve this it is better to allow the users to withdraw the balance themselves, so they pay for the gas. Or in fact you can allow anybody to make that call. So you can offer a call refund(account:uint256) which transfers the balance (if any) to given account. Note that this would not be using msg.sender, so that anybody (including the admin) can do this transfer.
Keep in mind they need to know that they have a balance, so make sure you're emitting an event or similar. Also provide a balanceOf(address) call so they can check.
Hope this makes sense & works for you.