Solidity variable definition: (bool sent, ) - solidity

In Solidity, this sentence:
(bool sent, ) = msg.sender.call{value: _amount}("");
What is the sense of that "," after sent variable?
Any link to offcial documentation?
Many thanks.

It means you do not need to define both the variables to access the return values. You can access either of these variables as follows
(,uint256 alpha) = testFunction(); //access first returned variable
(uint256 beta,) = testFunction(); //access second returned variable
function testFunction() public pure returns(uint256,uint256){
return (1,2);
}

Solidity functions can return multiple variables of different types.
If you only want to keep one variable, then you can declare a variable and then use commas:
function multiValueFunction() public returns (bool, string memory, uint[] memory, uint {
//do something
return (true, "New String", [1,2], 21)
}
function differentFunction() public {
uint numberToKeep;
(,,,numberToKeep) = multiValueFunction();
}
Expected: numberToKeep = 21
Each comma represents the place of a returned variable (that is not kept)

It just means that the function will return two variables and you just want to store the first one.

This kind of syntax (variable type) is called Tuple In Python and other languages.
In Solidity,
they're not considered a proper type but can be used as a shorthand.
See the Official Docs: Destructuring Assignments and Returning Multiple Values
example:
uint256 amount = 10 ether;
require(
amount <= address(this).balance,
"Trying to withdraw more money than the contract has."
);
(bool success, ) = (msg.sender).call{value: amount}("");
require(success, "Failed to withdraw money from contract.");
above code, Roughly, Can be translated with basic if else statements like following:
uint256 amount = 10 ether;
bool success;
if(amount <= address(this).balance) {
success = true;
} else {
success = false;
return "Trying to withdraw more money than the contract has.";
}
if(success) {
(msg.sender).call{value: amount}("")
} else {
return "Failed to withdraw money from contract.";
}
here's another contract as example,
use this link https://remix.ethereum.org/#version=soljson-v0.6.9+commit.3e3065ac.js&optimize=false&gist=83bfbd85ef79387f760154999eb4f192&runs=200&evmVersion=null to play around in remix online
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract myContract {
uint index;
function myFunction() public {
( , , uint256 standardDepositAmount, , ) = returnTuple();
require(standardDepositAmount == 3);
// do something...
}
function returnTuple() public pure returns (uint, uint, uint, uint, uint) {
return (1, 2, 3, 4, 5);
}
}

Related

Is it correct to use revert this way?

I have an abstract contract and I need to validate the parameters and return an error if not valid and also return the gas fees.
I created a modifier called checkNumber and inside I validate the _number and use require and revert.
CODE
//SPDX-License-Identifier: UNLICENSED
// Solidity files have to start with this pragma.
// It will be used by the Solidity compiler to validate its version.
pragma solidity >=0.7.0 <0.9.0;
struct Information {
uint number;
string avatar;
}
abstract contract AbstractCandidate {
uint[6] private _numbers = [1, 2, 3, 4, 5, 6];
string[6] private _avatars = [
"https://raw.githubusercontent.com/thiagosaud/dApp-superior-electoral-court/main/temp/imgs/candidate-1.png",
"https://raw.githubusercontent.com/thiagosaud/dApp-superior-electoral-court/main/temp/imgs/candidate-2.png",
"https://raw.githubusercontent.com/thiagosaud/dApp-superior-electoral-court/main/temp/imgs/candidate-3.png",
"https://raw.githubusercontent.com/thiagosaud/dApp-superior-electoral-court/main/temp/imgs/candidate-4.png",
"https://raw.githubusercontent.com/thiagosaud/dApp-superior-electoral-court/main/temp/imgs/candidate-5.png",
"https://raw.githubusercontent.com/thiagosaud/dApp-superior-electoral-court/main/temp/imgs/candidate-6.png"
];
modifier checkNumber(uint _number) {
string memory _errorMessage = "Candidate number is incorret!";
require(_number < 1 || _number > _numbers.length, _errorMessage);
if (_number < 1 || _number > _numbers.length) {
revert(_errorMessage);
}
_;
}
function getInformation(uint _number) external view checkNumber(_number) returns(Information memory) {
return Information({ avatar: _avatars[_number], number: _numbers[_number] });
}
}
According to this logic you will always get _errorMessage. For example in require statement if _number 0 you wont get err, but youll get it in if statement, because 0 < 1 and it fits to your if statement condition.

ERC721A smart contract

I'm writing an ERC721A smart contract and getting a warning in the Remix IDE. There is the code:
function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) {
if (index >= balanceOf(owner)) revert OwnerIndexOutOfBounds();
uint256 numMintedSoFar = totalSupply();
uint256 tokenIdsIdx;
address currOwnershipAddr;
// Counter overflow is impossible as the loop breaks when uint256 i is equal to another uint256 numMintedSoFar.
unchecked {
for (uint256 i; i < numMintedSoFar; i++) {
TokenOwnership memory ownership = _ownerships[i];
if (ownership.addr != address(0)) {
currOwnershipAddr = ownership.addr;
}
if (currOwnershipAddr == owner) {
if (tokenIdsIdx == index) {
return i;
}
tokenIdsIdx++;
}
}
}
// Execution should never reach this point.
assert(false);
}
This code is from the Square Bears collection ( https://etherscan.io/address/0x2b1037def2aa4ed427627903bdef9bdd27ae1ea3#code ). I got it from a YouTube tutorial. I think the code works, but I keep getting a warning.
Warning: Unnamed return variable can remain unassigned. Add an explicit return with value to all non-reverting code paths or name the variable.
--> contracts/ERC721A.sol:103:94:
|
103 | function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) {
| ^^^^^^^
I assume that I have to provide a named return value or variable, but the code seems to return an iterated value (i).
Because you've told the compiler that you will return a value from the function, but you didn't.
You should return a mock value even if you don't need to.
...
// Execution should never reach this point.
assert(false);
return tokenIdsIdx; // or simply return 0;
}

TypeError: Different number of arguments in return statement than in returns declaration

i need to write a contract with function that returns me the value balance of the wallet increased by 1. can you tell me whats wrong with my code? i am beginner in the solidity.
contract balance {
address owner;
uint a = 0;
uint b = 1;
mapping(address => uint) public balanc;
function balancecosh() public {
a = a + b;
return a;
}
}
Your balancecosh() function doesn't declare returning any values but then it returns one.
Add returns (uint) the function declaration:
function balancecosh() public returns (uint) {
a = a + b;
return a;
}
Try this.
pragma solidity ^0.4.24;
contract balance {
address owner;
mapping(address => uint256) public balances;
constructor() public {
// If you declare variables - initialize them
owner = msg.sender;
}
// Returns only if called from another function
function balanceIncrement(address _address) public returns (uint256){
// If you initialize owner - check it
require(owner == msg.sender, "Only owner can increment balances");
return balances[_address]++;
}
// Returns without modifying chain
function balanceViewIncrement(address _address) public view returns (uint256 value){
value = balances[_address];
value++;
}
}

There is Array.push function in solidity how it is return length of the array?

pragma solidity >=0.5.0 <0.6.0;
contract ZombieFactory {
event NewZombie(uint zombieId, string name, uint dna);
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
struct Zombie {
string name;
uint dna;
}
Zombie[] public zombies;
function _createZombie(string memory _name, uint _dna) private {
uint id = zombies.push(Zombie(_name, _dna)) - 1; //**here how it is return length of array**
emit NewZombie(id, _name, _dna);
}
function _generateRandomDna(string memory _str) private view returns (uint) {
uint rand = uint(keccak256(abi.encodePacked(_str)));
return rand % dnaModulus;
}
function createRandomZombie(string memory _name) public {
uint randDna = _generateRandomDna(_name);
_createZombie(_name, randDna);
}
}
I want to know how it is working i tired to searched in google but i cant get exact results try to explain how it returning length of array and basically it just add the element ...
before solidity v0.6.
Arrays have a member "push" define as :
Dynamic storage arrays and bytes (not string) have a member function called push that you can use to append an element at the end of the array. The element will be zero-initialised. The function returns the new length.
It's changed after v0.6.
Reference https://docs.soliditylang.org/en/v0.8.12/060-breaking-changes.html

Type error: Member not found or visible in unit256

I have this crowdfunding platform that was initially using SafeMath library. And since is deprecated I'm looking for a workaround to make it compile and I'm getting a compilation error with remix in line 131:
contributions[msg.sender] = contributions[msg.sender].add(msg.value);
Here you have the whole contract code, it's a platform where you can create projects and raise funds:
// We will be using Solidity version 0.6.0
pragma solidity 0.6.0;
// Importing OpenZeppelin's SafeMath Implementation
//import 'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/SafeMath.sol';
//import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/mocks/SafeMathMock.sol";
//import "#openzeppelin/contracts/utils/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,
uint deadline,
uint 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));
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');
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 {
// not 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;
}
}
The Using X for Y expression extends the Y datatype with functions of the X library.
In case of using SafeMath for uint256, it allows to use the functions defined in SafeMath (such as add()) on uint256 variables.
Specifically, function add() in SafeMath checks whether the addition would overflow the 256bit unsigned integer. If it did overflow, it throws an exception. If it didn't overflow, it returns the result of the addition.
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
You can achieve the same result with this snippet:
uint256 contribution = contributions[msg.sender] + msg.value; // c = a + b
require(contribution >= contributions[msg.sender]); // require(c >= a)
contributions[msg.sender] = contribution; // return c
If you switch to Solidity 0.8+, this is not needed, because since version 0.8.0, Solidity performs the overflow check automatically and reverts if an overflow/underflow would occur. So it would be sufficient to use just this snippet:
// safe in Solidity 0.8+, unsafe in older versions
contributions[msg.sender] += msg.value;
Arithmetic operations revert on underflow and overflow. You can use unchecked { ... } to use the previous wrapping behaviour.
Source: docs