I'm learning how the Uniswapv2 contracts work but I can't seem to wrap my mind around the swap() function.
Reference: https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Pair.sol#L173
Lines 173-174 contain:
balance0 = IERC20(_token0).balanceOf(address(this));
balance1 = IERC20(_token1).balanceOf(address(this));
My question is, when & whose balances are these?
A. These are the same as _reserve0 & _reserve1 after the most recent swap and will be used to synchronize reserves.
B. These are the quantities of each token the user making the swap currently possesses.
C. None of the above. It's something else. Please explain the flow of this function. I cannot find a clear and concise definition anywhere.
answer is "C" :)
balanceOf is a mapping in ERC20 implementation to return the amount that given address holds:
// address => holds uint amount
mapping(address => uint) public balanceOf;
Since current contract is inheriting from UniswapV2ERC20:
contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20{}
it can access to UniswapV2ERC20.sol
Since the mapping balanceOf is public, solidity assigns getters to the public variables
In the functions:
balance0 = IERC20(_token0).balanceOf(address(this));
balance1 = IERC20(_token1).balanceOf(address(this));
address(this) refers to the current contract which is UniswapV2Pair. So balance0 is how much the current contract owns _token0 and balance1 is how much the current contract address owns _token1. token0 and token1 are contract addresses and each ERC20 token contract, keeps track of addresses and their balances. so you are visiting each token contract and getting how much balance the current contract has.
Think ERC20 contract like a bank. you have token0 bank and token1 bank. Each bank keeps track of the balances of their users. balancesOf is where ERC20 tokens store those balances. Your current contract also owns some of those tokens so you just want to get how much tokens the current contract holds
swap function will be called by the user. Before executing the swap, contract checks if it has enough funds
uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT');
the Error being specified is
revert
The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
Debug the transaction to get more information.
//SPDX-License-Identifier:MIT
pragma solidity 0.8.8;
contract Giftcard{
event UniqueCardId(uint indexed Id,address indexed owner);
//Enter The Giftcard amount
//Pay the gift card by making multiple transations
//require(giftcard owner should approve the withdrawl )
address[] Giftcardowners;
mapping(address => uint) amountUploaded;
function Addamount() external payable{
require(msg.value >= 1 ether,"Gift card amount to small");
amountUploaded[msg.sender] = msg.value;
Giftcardowners.push(msg.sender);
emit UniqueCardId(Giftcardowners.length-1,msg.sender);
}
function GetGiftcard(uint _cardId) payable external {
require(Giftcardowners.length > _cardId,"Id doesnot exits");
address owner = Giftcardowners[_cardId-1];
uint amount = amountUploaded[owner];
require(amount >= 1 ether,"transfered is less than 1 ether");
// (bool successs,) = payable(msg.sender).call{value:amount}("");
//require(successs,"transaction reverted");
payable(msg.sender).transfer(1 ether);
}
function getBalance() external view returns(uint balance){
return address(this).balance;
}
}
Firstly I called the Addamount function by paying more than 1 ether to the smart contract
now after that when the GetGiftcard function is called the transaction is reverted. I am unable to find a solution
unable to understand the concept
Error is here
address owner = Giftcardowners[_cardId-1];
should be
address owner = Giftcardowners[_cardId];
When you call addAmount, this line executes
Giftcardowners.push(msg.sender);
in the Giftcardowners array you have only 1 item
Giftcardowners=[0x7EF2e0048f5bAeDe046f6BF797943daF4ED8CB47]
when you call the GetGiftcard, you need to pass _cardId=0, you are actually assigning the index of the array as the id. when you pass 0, index will be -1 here
address owner = Giftcardowners[_cardId-1];
You cannot pass 1 to get 1-1=0, because you have this condition
require(Giftcardowners.length > _cardId,"Id doesnot exits");
I am writing a solidity smart contract in which users would be able add a string (eg. one line joke), and other users should be able to vote on these jokes. If there are for example a million jokes in the contract (all with a different vote count), Would it be possible to rank these jokes by vote count? Eg. display the highest voted 10 of the million jokes? I know it is possible on a small scale, but on a larger scale I'm not so sure.
A variant of the contract that implements the main functionality you need is attached below:
registration of "jokes" records
registration of voting without repeats
definition of the top 10 (I hope I was not mistaken in the sorting algorithm).
The hash from its text is used as the identifier of the "joke".
However, in order to provide users with quality functionality, you need an external application that will monitor the events JokeCreated and JokeVoted of this contract and maintain an external database of "jokes" records.
This is because Ethereum contracts are ineffective for iterative operations with large arrays and you need an external service to:
providing users with a common list of "jokes"
providing users with a general rating list of "jokes"
When using an external application, you can also exclude the function of determining the top 10 from the contract (in function VotesForJoke), which will significantly reduce the cost of the voting transaction.
In addition, you need to keep in mind the problem of identifying users to avoid re-voting, since in general it cannot be solved at the level of Ethereum itself.
pragma solidity ^0.5.8;
contract Jokes
{
struct Joke
{
string text ;
address sender ;
bytes32 author ;
uint256 votes ;
mapping (bytes32=>bool) voters ;
}
mapping (bytes32 => Joke) JokesList ;
bytes32[10] Top10 ;
event JokeCreated(bytes32 hash, string text, address sender, bytes32 author) ;
event JokeVoted (bytes32 hash, bytes32 voter) ;
constructor() public
{
}
function NewJoke(string memory text_, bytes32 author_) public
{
bytes32 hash ;
hash=keccak256(abi.encodePacked(text_)) ;
if(JokesList[hash].author!=0x00) require(false) ;
JokesList[hash] =Joke({ text: text_,
sender: tx.origin,
author: author_,
votes: 0 }) ;
emit JokeCreated(hash, text_, tx.origin, author_) ;
}
function VotesForJoke(bytes32 hash_, bytes32 voter_) public
{
uint256 votes ;
uint256 i ;
// Check for existance
if(JokesList[hash_].author==0x00) require(false) ;
// Check for re-voting
if(JokesList[hash_].voters[voter_]==true) require(false) ;
JokesList[hash_].voters[voter_]=true ;
JokesList[hash_].votes++ ;
// Ordering top 10
votes=JokesList[hash_].votes ;
for(i=9 ; i>=0 ; i--)
if(votes>=JokesList[Top10[i]].votes)
{
if(i!=9 && Top10[i]!=hash_) Top10[i+1]=Top10[i] ;
}
else
{
break ;
}
if(i!=9) Top10[i+1]=hash_ ;
// Emit event of voting
emit JokeVoted(hash_, voter_) ;
}
function GetJoke(bytes32 hash_) public view returns (string memory, address, bytes32,uint256 retVal)
{
return(JokesList[hash_].text, JokesList[hash_].sender, JokesList[hash_].author, JokesList[hash_].votes) ;
}
function GetTop10() public view returns (bytes32[10] memory retVal)
{
return(Top10) ;
}
}
I ran into this error while coding, and cannot find any legit reason for it. I have called and executed functions like this before. The code is:
implicit none
real et(5),k(5,4),v(5),f1,f2,f3,f4,f5,kk,t,h
integer i,j
do i=1,5
et(i)=i-1.0
v(i)=0.0
end do
h=0.01
kk=6.0
do j=1,1000
write(*,*) et(1),et(2),et(3),et(4),et(5),t
do i=1,5
et(i)=et(i)+h*v(i)
end do
k(1,1)=h*f1(et(1),et(2),t) !partcle,k_no
k(2,1)=h*f2(et(1),et(2),et(3),t)
k(3,1)=h*f3(et(2),et(3),et(4),t)
k(4,1)=h*f4(et(3),et(4),et(5),t)
k(5,1)=h*f5(et(4),et(5),t)
k(1,2)=h*f1(et(1)+0.5*k(1,1),et(2)+0.5*k(2,1),t+0.5*h)
k(2,2)=h*f2(et(1)+0.5*k(1,1),et(2)+0.5*k(2,1),et(3)+0.5*k(3,1),
+ t+0.5*h)
k(3,2)=h*f3(et(2)+0.5*k(2,1),et(3)+0.5*k(3,1),et(4)+0.5*k(4,1),
+ t+0.5*h)
k(4,2)=h*f4(et(3)+0.5*k(3,1),et(4)+0.5*k(4,1),et(5)+0.5*k(5,1),
+ t+0.5*h)
k(5,2)=h*f5(et(4)+0.5*k(4,1),et(5)+0.5*k(5,1),t+0.5*h)
k(1,3)=h*f1(et(1)+0.5*k(1,2),et(2)+0.5*k(2,2),t+0.5*h)
k(2,3)=h*f2(et(1)+0.5*k(1,2),et(2)+0.5*k(2,2),et(3)+0.5*k(3,2),
+ t+0.5*h)
k(3,3)=h*f3(et(2)+0.5*k(2,2),et(3)+0.5*k(3,2),et(4)+0.5*k(4,2),
+ t+0.5*h)
k(4,3)=h*f4(et(3)+0.5*k(3,2),et(4)+0.5*k(4,2),et(5)+0.5*k(5,2),
+ t+0.5*h)
k(5,3)=h*f5(et(4)+0.5*k(4,2),et(5)+0.5*k(5,2),t+0.5*h)
k(1,4)=h*f1(et(1)+k(1,1),et(2)+k(2,1),t+h)
k(2,4)=h*f2(et(1)+k(1,1),et(2)+k(2,1),et(3)+k(3,1),t+h)
k(3,4)=h*f3(et(2)+k(2,1),et(3)+k(3,1),et(4)+k(4,1),t+h)
k(4,4)=h*f4(et(3)+k(3,1),et(4)+k(4,1),et(5)+k(5,1),t+h)
k(5,4)=h*f5(et(4)+k(4,1),et(5)+k(5,1),t+h)
do i=1,5
v(i)=v(i)+(1.0/6.0)*(k(1,i)+2*k(2,i)+2*k(3,i)+k(4,i))
end do
end do
end program
real function f1(et(1),et(2),t)
f1=kk*(et(2)-et(1))+cos(2*t)
return
end function
real function f2(et(1),et(2),et(3),t)
f2=kk*(et(3)-2*et(2)+et(1))
return
end function
real function f3(et(2),et(3),et(4),t)
f3=kk*(et(4)-2*et(3)+et(2))
return
end function
real function f4(et(3),et(4),et(5),t)
f4=kk*(et(5)-2*et(4)+et(3))
return
end function
real function f5(et(4),et(5),t)
f5=kk*(et(4)-et(5))
return
end function
when compiled only gives this error :
implicit none
1
real function f1(et(1),et(2),t)
2
Error: Two main PROGRAMs at (1) and (2)
Can you please suggest debugging? Is there some issue in calling a function with arrays as argument?
You cannot name your variables or dummy arguments with parentheses:
real function f1(et(1),et(2),t)
You must name them normally with alphabetic characters and numbers only
real function f1(et1,et2,t)
I have the following code using a normal data context which works great:
var dc = new myDataContext();
Contract.Assume(dc.Cars!= null);
var cars = (from c in dc.Cars
where c.Owner == 'Jim'
select c).ToList();
However when I convert the filter to an extension method like this:
var dc = new myDataContext();
Contract.Assume(dc.Cars!= null);
var cars = dc.Cars.WithOwner('Jim');
public static IQueryable<Car> WithOwner(this IQueryable<Car> cars, string owner)
{
Contract.Requires(cars != null);
return cars.Where(c => c.Owner == owner);
}
I get the following warning:
warning : CodeContracts: requires unproven: source != null
My guess is that your warning is caused by the owner parameter, rather than the cars. Add a precondition in the WithOwner method to check if owner is not null.
public static IQueryable<Car> WithOwner(IQueryable<Car> cars, string owner)
{
Contract.Requires(cars != null);
Contract.Requires(!string.isNullOrEmpty(owner));
return cars.Where(c => c.Owner = owner);
}
In your first code sample, you have 'Jim' hard-coded, so no problems there because there is not something which can be null.
In your second example you created a method for which the static compiler cannot prove that the source ( being owner ) 'will never be null', as other code might call it with an invalid values.
I wonder how you get the code compiled with the Extension method since you are missing this keyword in your method signature.
public static IQueryable<Car> WithOwner(this IQueryable<Car> cars, string owner)
{
...
}
/KP
Its possible that your code snippet does not completely describe the code you are using.
Consider this snippet instead:
var dc = new myDataContext();
Contract.Assume(dc.Cars!= null);
var models = dc.Cars.WithOwner('Jim').Select(c => c.Model);
public static IQueryable<Car> WithOwner(this IQueryable<Car> cars, string owner)
{
Contract.Requires(cars != null);
return cars.Where(c => c.Owner == owner);
}
In this snipped its likely the runtime will complain with the warning you mentioned, but it is not complaining about Cars possibly being null, it is complaining about the result from WithOwner (passed into Select) possibly being null.
You can satisfy the runtime by ensuring that the result from your extension method will not be null:
Contract.Ensures(Contract.Result<IQueryable<Car>>() != null);
This contract should be ok because Where will not return null, but instead returns an Enumerable.Empty<T>() when there are no matches.
We fixed this a few releases back. The warning was due to some missing contracts around Linq expression construction etc. Linq expression methods have contracts and the C# compiler generates code that calls these methods. If we don't have enough post conditions on the called methods, then you can get these cryptic warnings about code that you don't even know is there (unless you look with ILdasm).